changeset 14556:00de23677256

Merge
author lana
date Thu, 12 Nov 2015 14:15:05 -0800
parents 16fc042acee6 2a49e593ad60
children aa0621638103 2d7da5f834b3
files
diffstat 332 files changed, 11693 insertions(+), 2292 deletions(-) [+]
line wrap: on
line diff
--- a/make/Import.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/Import.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 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
@@ -45,8 +45,16 @@
 #
 # Import hotspot
 #
+
+# Don't import jsig library for static builds
+ifneq ($(STATIC_BUILD), true)
+  JSIG_IMPORT = jsig.*
+else
+  JSIG_IMPORT = 
+endif
+
 HOTSPOT_BASE_IMPORT_FILES := \
-    $(addprefix $(LIBRARY_PREFIX), jvm.* jsig.* jvm_db.* jvm_dtrace.*) \
+    $(addprefix $(LIBRARY_PREFIX), jvm.* $(JSIG_IMPORT) jvm_db.* jvm_dtrace.*) \
     Xusage.txt \
     #
 
@@ -79,32 +87,34 @@
 
 ################################################################################
 
-ifeq ($(OPENJDK_TARGET_OS), macosx)
-  JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
-      $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
-else
-  JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
-      $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
-endif
+ifneq ($(STATIC_BUILD), true)
+  ifeq ($(OPENJDK_TARGET_OS), macosx)
+    JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
+        $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+  else
+    JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
+        $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+  endif
 
-ifneq ($(OPENJDK_TARGET_OS), windows)
-  ifeq ($(JVM_VARIANT_SERVER), true)
-    BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-    ifneq (, $(JSIG_DEBUGINFO))
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+  ifneq ($(OPENJDK_TARGET_OS), windows)
+    ifeq ($(JVM_VARIANT_SERVER), true)
+      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+      ifneq (, $(JSIG_DEBUGINFO))
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+      endif
     endif
-  endif
-  ifeq ($(JVM_VARIANT_CLIENT), true)
-    BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-    ifneq (, $(JSIG_DEBUGINFO))
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+    ifeq ($(JVM_VARIANT_CLIENT), true)
+      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+      ifneq (, $(JSIG_DEBUGINFO))
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+      endif
     endif
-  endif
-  ifneq ($(OPENJDK_TARGET_OS), macosx)
-    ifeq ($(JVM_VARIANT_MINIMAL1), true)
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-      ifneq (,$(JSIG_DEBUGINFO))
-        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+    ifneq ($(OPENJDK_TARGET_OS), macosx)
+      ifeq ($(JVM_VARIANT_MINIMAL1), true)
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+        ifneq (,$(JSIG_DEBUGINFO))
+          BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+        endif
       endif
     endif
   endif
--- a/make/data/charsetmapping/DoubleByte-X.java.template	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/data/charsetmapping/DoubleByte-X.java.template	Thu Nov 12 14:15:05 2015 -0800
@@ -50,12 +50,12 @@
 
     public CharsetDecoder newDecoder() {
         initb2c();
-        return new  DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$);
+        return new  DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$);
     }
 
     public CharsetEncoder newEncoder() {
         initc2b();
-        return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex); 
+        return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$);
     }
 
     $B2C$
--- a/make/data/charsetmapping/SingleByte-X.java.template	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/data/charsetmapping/SingleByte-X.java.template	Thu Nov 12 14:15:05 2015 -0800
@@ -48,11 +48,11 @@
     }
 
     public CharsetDecoder newDecoder() {
-        return new SingleByte.Decoder(this, b2c);
+        return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$);
     }
 
     public CharsetEncoder newEncoder() {
-        return new SingleByte.Encoder(this, c2b, c2bIndex);
+        return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$);
     }
 
     private final static String b2cTable = $B2CTABLE$
--- a/make/gensrc/Gensrc-java.base.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-java.base.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -38,15 +38,15 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,LIST_RESOURCE_BUNDLE, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources, \
+    CLASS := ListResourceBundle, \
+))
 
-$(eval $(call SetupCompileProperties,SUN_UTIL, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources)), \
-    sun.util.resources.LocaleNamesBundle))
+$(eval $(call SetupCompileProperties, SUN_UTIL, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources, \
+    CLASS := sun.util.resources.LocaleNamesBundle, \
+))
 
 GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL)
 
--- a/make/gensrc/Gensrc-java.desktop.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-java.desktop.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -66,11 +66,11 @@
   PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources
 endif
 
-PROP_SRC_FILES := $(filter-out %cursors.properties, \
-    $(filter %.properties, $(call CacheFind, $(PROP_SRC_DIRS))))
-
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(PROP_SRC_FILES), ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(PROP_SRC_DIRS), \
+    EXCLUDE := %cursors.properties, \
+    CLASS := ListResourceBundle, \
+))
 
 GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-java.logging.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-java.logging.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -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
@@ -29,10 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-java.management.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-java.management.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,10 +32,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-jdk.dev.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-jdk.dev.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -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
@@ -29,11 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, \
-            $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-jdk.jartool.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-jdk.jartool.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -29,11 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, \
-            $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-jdk.jdi.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-jdk.jdi.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 JAVA_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/com/sun/tools/jdi/JDWP.java
 
 # Both the header and java file are created using the same recipe. By declaring
-# this rule and adding header file to dependencies for java file, both are 
+# this rule and adding header file to dependencies for java file, both are
 # rebuilt if either is missing
 $(HEADER_FILE): $(JDWP_SPEC_FILE) $(BUILD_TOOLS_JDK)
 
@@ -90,10 +90,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 GENSRC_JDK_JDI += $(COMPILE_PROPERTIES)
 
--- a/make/gensrc/Gensrc-jdk.localedata.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/Gensrc-jdk.localedata.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -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
@@ -35,10 +35,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \
-    sun.util.resources.LocaleNamesBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources, \
+    CLASS := sun.util.resources.LocaleNamesBundle, \
+))
 
 # Skip generating zh_HK from zh_TW for this module.
 GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES))
--- a/make/gensrc/GensrcProperties.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/gensrc/GensrcProperties.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -49,30 +49,40 @@
 endef
 
 ################################################################################
-# Creates a rule that runs CompileProperties on a set of properties files.
-# Param 1 - Variable to add targets to, must not contain space
-# Param 2 - Properties files to process
-# Param 3 - The super class for the generated classes
-# Param 4 - Module path root, defaults to $(JDK_TOPDIR)/src
-define SetupCompileProperties
-  $1_SRCS := $2
-  $1_CLASS := $3
-  $1_MODULE_PATH_ROOT := $4
-
+# Setup make rules that runs CompileProperties on a set of properties files.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+# SRC_DIRS   Directories containing properties files to process.
+# EXCLUDE   Exclude files matching this pattern.
+# CLASS   The super class for the generated classes.
+# MODULE_PATH_ROOT   Module path root, defaults to $(JDK_TOPDIR)/src.
+SetupCompileProperties = $(NamedParamsMacroTemplate)
+define SetupCompilePropertiesBody
+  # Set default value unless overridden
   ifeq ($$($1_MODULE_PATH_ROOT), )
     $1_MODULE_PATH_ROOT := $(JDK_TOPDIR)/src
   endif
 
+  # Locate all properties files in the given source dirs.
+  $1_SRC_FILES := $$(filter %.properties, $$(call CacheFind, $$($1_SRC_DIRS)))
+
+  ifneq ($$($1_EXCLUDE), )
+    $1_SRC_FILES := $$(filter-out $$($1_EXCLUDE), $$($1_SRC_FILES))
+  endif
+
   # Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties
   # to .../support/gensrc/<module>/com/sun/tools/javac/resources/javac_zh_CN.java
-  # Strip away prefix and suffix, leaving for example only: 
+  # Strip away prefix and suffix, leaving for example only:
   # "<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN"
   $1_JAVAS := $$(patsubst $$($1_MODULE_PATH_ROOT)/%, \
       $(SUPPORT_OUTPUTDIR)/gensrc/%, \
       $$(patsubst %.properties, %.java, \
       $$(subst /$(OPENJDK_TARGET_OS)/classes,, \
       $$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \
-      $$(subst /share/classes,, $$($1_SRCS))))))
+      $$(subst /share/classes,, $$($1_SRC_FILES))))))
 
   # Generate the package dirs for the to be generated java files. Sort to remove
   # duplicates.
@@ -82,22 +92,22 @@
   # "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle"
   # suitable to be fed into the CompileProperties command.
   $1_CMDLINE := $$(subst _SPACE_, $(SPACE), \
-      $$(join $$(addprefix -compile_SPACE_, $$($1_SRCS)), \
+      $$(join $$(addprefix -compile_SPACE_, $$($1_SRC_FILES)), \
       $$(addsuffix _SPACE_$$($1_CLASS), \
       $$(addprefix _SPACE_, $$($1_JAVAS)))))
 
-  $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.done
+  $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.marker
   $1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline
 
 # Now setup the rule for the generation of the resource bundles.
-  $$($1_TARGET): $$($1_SRCS) $$($1_JAVAS) $(BUILD_TOOLS_JDK)
+  $$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $(BUILD_TOOLS_JDK)
 	$(MKDIR) -p $$(@D) $$($1_DIRS)
-	$(ECHO) Compiling $$(words $$($1_SRCS)) properties into resource bundles for $(MODULE)
+	$(ECHO) Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE)
 	$$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE)))
 	$(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE)
 	$(TOUCH) $$@
 
-  $$($1_JAVAS): $$($1_SRCS)
+  $$($1_JAVAS): $$($1_SRC_FILES)
 
   # Create zh_HK versions of all zh_TW files created above
   $$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS))))
--- a/make/launcher/LauncherCommon.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/launcher/LauncherCommon.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -122,8 +122,23 @@
     endif
 
     $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"'
-    $1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \
+    $1_LDFLAGS += -Wl,-all_load \
         -sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE)
+    ifeq ($(STATIC_BUILD), true)
+      $1_LDFLAGS += -exported_symbols_list \
+              $(SUPPORT_OUTPUTDIR)/build-static/exported.symbols
+      $1_LIBS += \
+          $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/java.base -name "*.a") \
+          $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libdt_socket.a \
+          $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libjdwp.a \
+          $(SUPPORT_OUTPUTDIR)/native/java.base/$(LIBRARY_PREFIX)fdlibm$(STATIC_LIBRARY_SUFFIX) \
+          -framework CoreFoundation \
+          -framework Foundation \
+          -framework SystemConfiguration \
+          -lstdc++ -liconv
+    else
+      $1_LIBS += $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a
+    endif
     $1_LIBS += -framework Cocoa -framework Security \
         -framework ApplicationServices
   endif
--- a/make/lib/Awt2dLibraries.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -476,7 +476,7 @@
 ifeq ($(USE_EXTERNAL_LIBJPEG), true)
   LIBJPEG_LIBS := -ljpeg
   BUILD_LIBJAVAJPEG_INCLUDE_FILES := \
-      imageIOJPEG.c \
+      imageioJPEG.c \
       jpegdecoder.c
   BUILD_LIBJAVAJPEG_HEADERS :=
 else
--- a/make/lib/CoreLibraries.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/lib/CoreLibraries.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -435,10 +435,14 @@
       OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \
       DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
 
-  $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC)
+  ifeq ($(STATIC_BUILD), true)
+    TARGETS += $(BUILD_LIBJLI_STATIC)
+  else
+    $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC)
 	$(call install-file)
 
-  TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a
+    TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a
+  endif
 
 else ifeq ($(OPENJDK_TARGET_OS), aix)
   # AIX also requires a static libjli because the compiler doesn't support '-rpath'
--- a/make/lib/Lib-java.base.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/lib/Lib-java.base.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -33,3 +33,29 @@
 include NetworkingLibraries.gmk
 include NioLibraries.gmk
 include SecurityLibraries.gmk
+
+ifeq ($(STATIC_BUILD), true)
+  JAVA_BASE_EXPORT_SYMBOLS_SRC := \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli/$(LIBRARY_PREFIX)jli.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)java.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)net.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)nio.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)verify.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)zip.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)jimage.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/server/$(LIBRARY_PREFIX)jvm.symbols \
+      #
+
+  JAVA_BASE_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/java.base.symbols
+
+  $(JAVA_BASE_EXPORT_SYMBOL_FILE): $(JAVA_BASE_EXPORT_SYMBOLS_SRC)
+	$(ECHO) $(LOG_INFO) "Generating java.base.symbols file"
+	$(CAT) $^ > $@
+
+  # The individual symbol files is generated when the respective lib is built
+  $(JAVA_BASE_EXPORT_SYMBOLS_SRC): $(BUILD_LIBJLI) $(BUILD_LIBJAVA) \
+      $(BUILD_LIBNET) $(BUILD_LIBNIO) $(BUILD_LIBVERIFY) $(BUILD_LIBZIP) \
+      $(BUILD_LIBJIMAGE)
+
+  TARGETS += $(JAVA_BASE_EXPORT_SYMBOL_FILE)
+endif
--- a/make/lib/Lib-jdk.jdwp.agent.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/lib/Lib-jdk.jdwp.agent.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -102,3 +102,23 @@
 TARGETS += $(BUILD_LIBJDWP)
 
 ################################################################################
+
+ifeq ($(STATIC_BUILD), true)
+  JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC := \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)dt_socket.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)jdwp.symbols
+
+  JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/jdk.jdwp.agent.symbols
+
+  $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE): $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC)
+	$(ECHO) $(LOG_INFO) "Generating jdk.jdwp.agent symbols file"
+	$(CAT) $^ > $@
+
+  # The individual symbol files is generated when the respective lib is built
+  $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC): $(BUILD_LIBDT_SOCKET) $(BUILD_LIBJDWP)
+
+  TARGETS += $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE)
+
+endif
+
+################################################################################
--- a/make/lib/SecurityLibraries.gmk	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/lib/SecurityLibraries.gmk	Thu Nov 12 14:15:05 2015 -0800
@@ -26,38 +26,41 @@
 include LibCommon.gmk
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
+  # JavaNativeFoundation framework not supported in static builds 
+  ifneq ($(STATIC_BUILD), true)
 
   ################################################################################
 
-  LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
-  LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
-      $(LIBJAVA_HEADER_FLAGS) \
-      -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+    LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
+    LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
+        $(LIBJAVA_HEADER_FLAGS) \
+        -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
 
-  $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
-      LIBRARY := osxsecurity, \
-      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-      SRC := $(LIBOSXSECURITY_DIRS), \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB) \
-          $(LIBOSXSECURITY_CFLAGS), \
-      DISABLED_WARNINGS_clang := deprecated-declarations, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) \
-          -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
-          $(call SET_SHARED_LIBRARY_ORIGIN) \
-          -fobjc-link-runtime, \
-      LIBS := \
-          -framework JavaNativeFoundation \
-          -framework CoreServices \
-          -framework Security \
-          $(JDKLIB_LIBS), \
-      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
-      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+    $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
+        LIBRARY := osxsecurity, \
+        OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+        SRC := $(LIBOSXSECURITY_DIRS), \
+        OPTIMIZATION := LOW, \
+        CFLAGS := $(CFLAGS_JDKLIB) \
+            $(LIBOSXSECURITY_CFLAGS), \
+        DISABLED_WARNINGS_clang := deprecated-declarations, \
+        LDFLAGS := $(LDFLAGS_JDKLIB) \
+            -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
+            $(call SET_SHARED_LIBRARY_ORIGIN) \
+            -fobjc-link-runtime, \
+        LIBS := \
+            -framework JavaNativeFoundation \
+            -framework CoreServices \
+            -framework Security \
+            $(JDKLIB_LIBS), \
+        OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
+        DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
 
-  $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
+    $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
 
-  TARGETS += $(BUILD_LIBOSXSECURITY)
+    TARGETS += $(BUILD_LIBOSXSECURITY)
 
   ################################################################################
 
+  endif
 endif
--- a/make/mapfiles/libjava/mapfile-vers	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/mapfiles/libjava/mapfile-vers	Thu Nov 12 14:15:05 2015 -0800
@@ -211,6 +211,7 @@
 		Java_java_lang_SecurityManager_getClassContext;
 		Java_java_lang_Shutdown_halt0;
 		Java_java_lang_String_intern;
+		Java_java_lang_StringUTF16_isBigEndian;
 		Java_java_lang_System_identityHashCode;
 		Java_java_lang_System_initProperties;
 		Java_java_lang_System_mapLibraryName;
--- a/make/mapfiles/libjava/reorder-sparc	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/mapfiles/libjava/reorder-sparc	Thu Nov 12 14:15:05 2015 -0800
@@ -57,6 +57,7 @@
 text: .text%JNU_ClassString;
 text: .text%JNU_CopyObjectArray;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
 text: .text%Java_java_lang_ClassLoader_findBootstrapClass;
 text: .text%Java_java_lang_Throwable_fillInStackTrace;
--- a/make/mapfiles/libjava/reorder-sparcv9	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/mapfiles/libjava/reorder-sparcv9	Thu Nov 12 14:15:05 2015 -0800
@@ -29,6 +29,7 @@
 text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
 text: .text%Java_java_lang_Class_forName0;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_java_lang_Float_floatToRawIntBits;
 text: .text%Java_java_lang_Double_doubleToRawLongBits;
 text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
--- a/make/mapfiles/libjava/reorder-x86	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/mapfiles/libjava/reorder-x86	Thu Nov 12 14:15:05 2015 -0800
@@ -31,6 +31,7 @@
 text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
 text: .text%Java_java_lang_Class_forName0;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
 text: .text%Java_java_lang_Throwable_fillInStackTrace;
 text: .text%Java_java_lang_System_setOut0;
--- a/make/mapfiles/libnio/mapfile-macosx	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/mapfiles/libnio/mapfile-macosx	Thu Nov 12 14:15:05 2015 -0800
@@ -75,6 +75,7 @@
                 Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
+                Java_sun_nio_ch_IOUtil_iovMax;
 		Java_sun_nio_ch_KQueue_kqueue;
 		Java_sun_nio_ch_KQueue_keventRegister;
 		Java_sun_nio_ch_KQueue_keventPoll;
--- a/make/src/classes/build/tools/charsetmapping/DBCS.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/src/classes/build/tools/charsetmapping/DBCS.java	Thu Nov 12 14:15:05 2015 -0800
@@ -197,6 +197,7 @@
                        .replace("$B1MAX$"   , "0x" + Integer.toString(b1Max, 16))
                        .replace("$B2MIN$"   , "0x" + Integer.toString(b2Min, 16))
                        .replace("$B2MAX$"   , "0x" + Integer.toString(b2Max, 16))
+                       .replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false")
                        .replace("$B2C$", b2c)
                        .replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16))
                        .replace("$NONROUNDTRIP_B2C$", b2cNR)
--- a/make/src/classes/build/tools/charsetmapping/SBCS.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/src/classes/build/tools/charsetmapping/SBCS.java	Thu Nov 12 14:15:05 2015 -0800
@@ -175,6 +175,9 @@
                 else
                     line = "        return (cs instanceof " + clzName + ");";
             }
+            if (line.indexOf("$ASCIICOMPATIBLE$") != -1) {
+                line = line.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false");
+            }
             if (line.indexOf("$B2CTABLE$") != -1) {
                 line = line.replace("$B2CTABLE$", b2c);
             }
--- a/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java	Thu Nov 12 14:15:05 2015 -0800
@@ -841,7 +841,7 @@
                 pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
 
                 pw.println("package "+package_name+";\n");
-                pw.println("import sun.misc.*;\n");
+                pw.println("import jdk.internal.misc.Unsafe;\n");
                 pw.println("import sun.util.logging.PlatformLogger;");
                 String baseClass = stp.getBaseClass();
                 if (baseClass == null) {
@@ -941,7 +941,7 @@
             pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
 
             pw.println("package "+package_name+";\n");
-            pw.println("import sun.misc.Unsafe;\n");
+            pw.println("import jdk.internal.misc.Unsafe;\n");
             pw.println("class " + ft.getName() + " {");
             pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;");
             pw.println("\tprivate boolean __executed = false;");
--- a/src/demo/share/jvmti/agent_util/agent_util.h	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/agent_util/agent_util.h	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -65,6 +65,51 @@
 void *allocate(jvmtiEnv *jvmti, jint len);
 void  add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name);
 
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * Agent library Load/Attach/Unload functions
+ *
+ * DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
+ * generate the appropriate entrypoint names based on static
+ * versus dynamic builds.
+ *
+ * STATIC_BUILD must be defined to build static versions of these libraries.
+ * LIBRARY_NAME must be set to the name of the library for static builds.
+ */
+#define ADD_LIB_NAME3(name, lib) name ## lib
+#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
+#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
+
+#define DEF_Agent_OnLoad \
+ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
+
+#define DEF_Agent_OnAttach \
+ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
+
+#define DEF_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
+{ \
+  void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
+  ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
+} \
+void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
+
+#else
+#define DEF_Agent_OnLoad Agent_OnLoad
+#define DEF_Agent_OnAttach Agent_OnAttach
+#define DEF_Agent_OnUnload Agent_OnUnload
+#endif
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
--- a/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -225,7 +225,7 @@
  * event here.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -272,6 +272,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/src/demo/share/jvmti/gctest/gctest.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/gctest/gctest.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -148,7 +148,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -193,6 +193,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/src/demo/share/jvmti/heapTracker/heapTracker.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/heapTracker/heapTracker.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -894,7 +894,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -1010,7 +1010,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Skip any cleanup, VM is about to die anyway */
 }
--- a/src/demo/share/jvmti/heapTracker/heapTracker.h	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/heapTracker/heapTracker.h	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/src/demo/share/jvmti/heapViewer/heapViewer.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/heapViewer/heapViewer.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -235,7 +235,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -283,6 +283,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/src/demo/share/jvmti/minst/minst.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/minst/minst.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -373,7 +373,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -467,7 +467,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Make sure all malloc/calloc/strdup space is freed */
     if ( gdata->include != NULL ) {
--- a/src/demo/share/jvmti/minst/minst.h	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/minst/minst.h	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/src/demo/share/jvmti/mtrace/mtrace.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/mtrace/mtrace.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -697,7 +697,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -795,7 +795,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Make sure all malloc/calloc/strdup space is freed */
     if ( gdata->include != NULL ) {
--- a/src/demo/share/jvmti/mtrace/mtrace.h	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/mtrace/mtrace.h	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/src/demo/share/jvmti/versionCheck/versionCheck.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/versionCheck/versionCheck.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -89,7 +89,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -116,6 +116,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/src/demo/share/jvmti/waiters/Monitor.hpp	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/waiters/Monitor.hpp	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,6 +37,10 @@
  * this sample code.
  */
 
+#ifdef STATIC_BUILD
+#define Monitor WaiterMonitor
+#endif
+
 
 /* C++ Monitor class */
 
--- a/src/demo/share/jvmti/waiters/Thread.cpp	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/waiters/Thread.cpp	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,6 +37,9 @@
  * this sample code.
  */
 
+#ifdef STATIC_BUILD
+#define Thread WaiterThread
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
--- a/src/demo/share/jvmti/waiters/waiters.cpp	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/demo/share/jvmti/waiters/waiters.cpp	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -243,7 +243,7 @@
 
     /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
     JNIEXPORT jint JNICALL
-    Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+    DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
     {
         jvmtiEnv           *jvmti;
         jint                rc;
@@ -288,7 +288,7 @@
 
     /* Agent_OnUnload() is called last */
     JNIEXPORT void JNICALL
-    Agent_OnUnload(JavaVM *vm)
+    DEF_Agent_OnUnload(JavaVM *vm)
     {
     }
 
--- a/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java	Thu Nov 12 14:15:05 2015 -0800
@@ -34,7 +34,7 @@
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * AsynchronousChannelGroup implementation based on the AIX pollset framework.
--- a/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Thu Nov 12 14:15:05 2015 -0800
@@ -26,7 +26,7 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Provides access to the Linux epoll facility.
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Thu Nov 12 14:15:05 2015 -0800
@@ -29,7 +29,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixNativeDispatcher.*;
 import static sun.nio.fs.UnixConstants.*;
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java	Thu Nov 12 14:15:05 2015 -0800
@@ -29,7 +29,7 @@
 import java.nio.ByteBuffer;
 import java.io.IOException;
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixConstants.*;
 import static sun.nio.fs.LinuxNativeDispatcher.*;
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java	Thu Nov 12 14:15:05 2015 -0800
@@ -30,7 +30,7 @@
 import java.security.PrivilegedAction;
 import java.util.*;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixNativeDispatcher.*;
 import static sun.nio.fs.UnixConstants.*;
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Thu Nov 12 14:15:05 2015 -0800
@@ -26,7 +26,7 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Provides access to the BSD kqueue facility.
--- a/src/java.base/macosx/native/libjava/java_props_macosx.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/macosx/native/libjava/java_props_macosx.c	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -35,13 +35,15 @@
 
 #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;
+#ifndef STATIC_BUILD
+// JavaRuntimeSupport doesn't support static Java runtimes
     if (jrsFwk == NULL) {
        jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
     }
+#endif
     return jrsFwk;
 }
 
--- a/src/java.base/macosx/native/libjli/java_md_macosx.c	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/macosx/native/libjli/java_md_macosx.c	Thu Nov 12 14:15:05 2015 -0800
@@ -245,6 +245,8 @@
     return sExportedJNIFunctions = fxns;
 }
 
+#ifndef STATIC_BUILD
+
 JNIEXPORT jint JNICALL
 JNI_GetDefaultJavaVMInitArgs(void *args) {
     InvocationFunctions *ifn = GetExportedJNIFunctions();
@@ -265,6 +267,7 @@
     if (ifn == NULL) return JNI_ERR;
     return ifn->GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
 }
+#endif
 
 /*
  * Allow JLI-aware launchers to specify a client/server preference
@@ -303,7 +306,12 @@
     objc_registerThreadWithCollector();
 
     if (main_fptr == NULL) {
+#ifdef STATIC_BUILD
+        extern int main(int argc, char **argv);
+        main_fptr = &main;
+#else
         main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
+#endif
         if (main_fptr == NULL) {
             JLI_ReportErrorMessageSys("error locating main entrypoint\n");
             exit(1);
@@ -588,6 +596,9 @@
 
     JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
 
+#ifdef STATIC_BUILD
+    return JNI_TRUE;
+#else
     if (stat(jvmpath, &s) == 0) {
         JLI_TraceLauncher("yes.\n");
         return JNI_TRUE;
@@ -595,6 +606,7 @@
         JLI_TraceLauncher("no.\n");
         return JNI_FALSE;
     }
+#endif
 }
 
 /*
@@ -607,10 +619,18 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
+#ifdef STATIC_BUILD
+        char jvm_cfg[MAXPATHLEN];
+        JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path);
+        if (access(jvm_cfg, F_OK) == 0) {
+            return JNI_TRUE;
+        }
+#else
         JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
         if (access(libjava, F_OK) == 0) {
             return JNI_TRUE;
         }
+#endif
         /* ensure storage for path + /jre + NULL */
         if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) {
             JLI_TraceLauncher("Insufficient space to store JRE path\n");
@@ -629,6 +649,24 @@
     Dl_info selfInfo;
     dladdr(&GetJREPath, &selfInfo);
 
+#ifdef STATIC_BUILD
+    char jvm_cfg[MAXPATHLEN];
+    char *p = NULL;
+    strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN);
+    p = strrchr(jvm_cfg, '/'); *p = '\0';
+    p = strrchr(jvm_cfg, '/');
+    if (strcmp(p, "/.") == 0) {
+      *p = '\0';
+      p = strrchr(jvm_cfg, '/'); *p = '\0';
+    }
+    else *p = '\0';
+    strncpy(path, jvm_cfg, pathsize);
+    strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN);
+    if (access(jvm_cfg, F_OK) == 0) {
+      return JNI_TRUE;
+    }
+#endif
+
     char *realPathToSelf = realpath(selfInfo.dli_fname, path);
     if (realPathToSelf != path) {
         return JNI_FALSE;
@@ -664,7 +702,11 @@
 
     JLI_TraceLauncher("JVM path is %s\n", jvmpath);
 
+#ifndef STATIC_BUILD
     libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
+#else
+    libjvm = dlopen(NULL, RTLD_FIRST);
+#endif
     if (libjvm == NULL) {
         JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
@@ -714,9 +756,14 @@
     char* exec_path = NULL;
     {
         Dl_info dlinfo;
+
+#ifdef STATIC_BUILD
+        void *fptr;
+        fptr = (void *)&SetExecname;
+#else
         int (*fptr)();
-
         fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
+#endif
         if (fptr == NULL) {
             JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
             return JNI_FALSE;
--- a/src/java.base/share/classes/java/io/File.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/io/File.java	Thu Nov 12 14:15:05 2015 -0800
@@ -2184,10 +2184,10 @@
 
     private static final long PATH_OFFSET;
     private static final long PREFIX_LENGTH_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             PATH_OFFSET = unsafe.objectFieldOffset(
                     File.class.getDeclaredField("path"));
             PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Nov 12 14:15:05 2015 -0800
@@ -40,7 +40,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.reflect.misc.ReflectUtil;
 
 /**
--- a/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Nov 12 14:15:05 2015 -0800
@@ -48,7 +48,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.ReflectionFactory;
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Nov 12 14:15:05 2015 -0800
@@ -31,6 +31,12 @@
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.UTF16;
+import static java.lang.String.LATIN1;
+import static java.lang.String.checkIndex;
+import static java.lang.String.checkOffset;
+
 /**
  * A mutable sequence of characters.
  * <p>
@@ -51,7 +57,12 @@
     /**
      * The value is used for character storage.
      */
-    char[] value;
+    byte[] value;
+
+    /**
+     * The id of the encoding used to encode the bytes in {@code value}.
+     */
+    byte coder;
 
     /**
      * The count is the number of characters used.
@@ -68,7 +79,13 @@
      * Creates an AbstractStringBuilder of the specified capacity.
      */
     AbstractStringBuilder(int capacity) {
-        value = new char[capacity];
+        if (COMPACT_STRINGS) {
+            value = new byte[capacity];
+            coder = LATIN1;
+        } else {
+            value = StringUTF16.newBytesFor(capacity);
+            coder = UTF16;
+        }
     }
 
     /**
@@ -90,7 +107,7 @@
      * @return  the current capacity
      */
     public int capacity() {
-        return value.length;
+        return value.length >> coder;
     }
 
     /**
@@ -110,8 +127,9 @@
      * @param   minimumCapacity   the minimum desired capacity.
      */
     public void ensureCapacity(int minimumCapacity) {
-        if (minimumCapacity > 0)
+        if (minimumCapacity > 0) {
             ensureCapacityInternal(minimumCapacity);
+        }
     }
 
     /**
@@ -120,24 +138,48 @@
      */
     private void ensureCapacityInternal(int minimumCapacity) {
         // overflow-conscious code
-        if (minimumCapacity - value.length > 0)
+        int capacity = value.length >> coder;
+        if (minimumCapacity - capacity > 0) {
             expandCapacity(minimumCapacity);
+        }
     }
 
     /**
      * This implements the expansion semantics of ensureCapacity with no
      * size check or synchronization.
      */
-    void expandCapacity(int minimumCapacity) {
-        int newCapacity = value.length * 2 + 2;
-        if (newCapacity - minimumCapacity < 0)
+    private void expandCapacity(int minimumCapacity) {
+        int newCapacity = (value.length >> coder) * 2 + 2;
+        if (newCapacity - minimumCapacity < 0) {
             newCapacity = minimumCapacity;
+        }
         if (newCapacity < 0) {
-            if (minimumCapacity < 0) // overflow
+            if (minimumCapacity < 0) {// overflow
                 throw new OutOfMemoryError();
+            }
             newCapacity = Integer.MAX_VALUE;
         }
-        value = Arrays.copyOf(value, newCapacity);
+        if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
+            if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
+                throw new OutOfMemoryError();
+            }
+            newCapacity = StringUTF16.MAX_LENGTH;
+        }
+        this.value = Arrays.copyOf(value, newCapacity << coder);
+    }
+
+    /**
+     * If the coder is "isLatin1", this inflates the internal 8-bit storage
+     * to 16-bit <hi=0, low> pair storage.
+     */
+    private void inflate() {
+        if (!isLatin1()) {
+            return;
+        }
+        byte[] buf = StringUTF16.newBytesFor(value.length);
+        StringLatin1.inflateSB(value, buf, 0, count);
+        this.value = buf;
+        this.coder = UTF16;
     }
 
     /**
@@ -148,8 +190,9 @@
      * returned by a subsequent call to the {@link #capacity()} method.
      */
     public void trimToSize() {
-        if (count < value.length) {
-            value = Arrays.copyOf(value, count);
+        int length = count << coder;
+        if (length < value.length) {
+            value = Arrays.copyOf(value, length);
         }
     }
 
@@ -179,14 +222,17 @@
      *               {@code newLength} argument is negative.
      */
     public void setLength(int newLength) {
-        if (newLength < 0)
+        if (newLength < 0) {
             throw new StringIndexOutOfBoundsException(newLength);
+        }
         ensureCapacityInternal(newLength);
-
         if (count < newLength) {
-            Arrays.fill(value, count, newLength, '\0');
+            if (isLatin1()) {
+                StringLatin1.fillNull(value, count, newLength);
+            } else {
+                StringUTF16.fillNull(value, count, newLength);
+            }
         }
-
         count = newLength;
     }
 
@@ -209,9 +255,11 @@
      */
     @Override
     public char charAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        return value[index];
+        checkIndex(index, count);
+        if (isLatin1()) {
+            return (char)(value[index] & 0xff);
+        }
+        return StringUTF16.charAt(value, index);
     }
 
     /**
@@ -236,10 +284,11 @@
      *             sequence.
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= count)) {
-            throw new StringIndexOutOfBoundsException(index);
+        checkIndex(index, count);
+        if (isLatin1()) {
+            return value[index] & 0xff;
         }
-        return Character.codePointAtImpl(value, index, count);
+        return StringUTF16.codePointAtSB(value, index, count);
     }
 
     /**
@@ -265,10 +314,13 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= count)) {
+        if (i < 0 || i >= count) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBeforeImpl(value, index, 0);
+        if (isLatin1()) {
+            return value[i] & 0xff;
+        }
+        return StringUTF16.codePointBeforeSB(value, index);
     }
 
     /**
@@ -295,7 +347,10 @@
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
+        if (isLatin1()) {
+            return endIndex - beginIndex;
+        }
+        return StringUTF16.codePointCountSB(value, beginIndex, endIndex);
     }
 
     /**
@@ -321,8 +376,8 @@
         if (index < 0 || index > count) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.offsetByCodePointsImpl(value, 0, count,
-                                                index, codePointOffset);
+        return Character.offsetByCodePoints(this,
+                                            index, codePointOffset);
     }
 
     /**
@@ -355,13 +410,14 @@
      */
     public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
     {
-        if (srcBegin < 0)
-            throw new StringIndexOutOfBoundsException(srcBegin);
-        if ((srcEnd < 0) || (srcEnd > count))
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        if (srcBegin > srcEnd)
-            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
-        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+        checkRangeSIOOBE(srcBegin, srcEnd, count);  // compatible to old version
+        int n = srcEnd - srcBegin;
+        checkRange(dstBegin, dstBegin + n, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
+        }
     }
 
     /**
@@ -379,9 +435,15 @@
      *             negative or greater than or equal to {@code length()}.
      */
     public void setCharAt(int index, char ch) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        value[index] = ch;
+        checkIndex(index, count);
+        if (isLatin1() && StringLatin1.canEncode(ch)) {
+            value[index] = (byte)ch;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, index, ch);
+        }
     }
 
     /**
@@ -418,35 +480,34 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder append(String str) {
-        if (str == null)
+        if (str == null) {
             return appendNull();
+        }
         int len = str.length();
         ensureCapacityInternal(count + len);
-        str.getChars(0, len, value, count);
+        putStringAt(count, str);
         count += len;
         return this;
     }
 
     // Documentation in subclasses because of synchro difference
     public AbstractStringBuilder append(StringBuffer sb) {
-        if (sb == null)
-            return appendNull();
-        int len = sb.length();
-        ensureCapacityInternal(count + len);
-        sb.getChars(0, len, value, count);
-        count += len;
-        return this;
+        return this.append((AbstractStringBuilder)sb);
     }
 
     /**
      * @since 1.8
      */
     AbstractStringBuilder append(AbstractStringBuilder asb) {
-        if (asb == null)
+        if (asb == null) {
             return appendNull();
+        }
         int len = asb.length();
         ensureCapacityInternal(count + len);
-        asb.getChars(0, len, value, count);
+        if (getCoder() != asb.getCoder()) {
+            inflate();
+        }
+        asb.getBytes(value, count, coder);
         count += len;
         return this;
     }
@@ -454,25 +515,35 @@
     // Documentation in subclasses because of synchro difference
     @Override
     public AbstractStringBuilder append(CharSequence s) {
-        if (s == null)
+        if (s == null) {
             return appendNull();
-        if (s instanceof String)
+        }
+        if (s instanceof String) {
             return this.append((String)s);
-        if (s instanceof AbstractStringBuilder)
+        }
+        if (s instanceof AbstractStringBuilder) {
             return this.append((AbstractStringBuilder)s);
-
+        }
         return this.append(s, 0, s.length());
     }
 
     private AbstractStringBuilder appendNull() {
-        int c = count;
-        ensureCapacityInternal(c + 4);
-        final char[] value = this.value;
-        value[c++] = 'n';
-        value[c++] = 'u';
-        value[c++] = 'l';
-        value[c++] = 'l';
-        count = c;
+        ensureCapacityInternal(count + 4);
+        int count = this.count;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            val[count++] = 'n';
+            val[count++] = 'u';
+            val[count++] = 'l';
+            val[count++] = 'l';
+        } else {
+            checkOffset(count + 4, val.length >> 1);
+            StringUTF16.putChar(val, count++, 'n');
+            StringUTF16.putChar(val, count++, 'u');
+            StringUTF16.putChar(val, count++, 'l');
+            StringUTF16.putChar(val, count++, 'l');
+        }
+        this.count = count;
         return this;
     }
 
@@ -507,21 +578,13 @@
      */
     @Override
     public AbstractStringBuilder append(CharSequence s, int start, int end) {
-        if (s == null)
+        if (s == null) {
             s = "null";
-        if ((start < 0) || (start > end) || (end > s.length()))
-            throw new IndexOutOfBoundsException(
-                "start " + start + ", end " + end + ", s.length() "
-                + s.length());
+        }
+        checkRange(start, end, s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        if (s instanceof String) {
-            ((String)s).getChars(start, end, value, count);
-        } else {
-            for (int i = start, j = count; i < end; i++, j++)
-                value[j] = s.charAt(i);
-        }
-        count += len;
+        appendChars(s, start, end);
         return this;
     }
 
@@ -544,8 +607,7 @@
     public AbstractStringBuilder append(char[] str) {
         int len = str.length;
         ensureCapacityInternal(count + len);
-        System.arraycopy(str, 0, value, count, len);
-        count += len;
+        appendChars(str, 0, len);
         return this;
     }
 
@@ -572,10 +634,10 @@
      *         or {@code offset+len > str.length}
      */
     public AbstractStringBuilder append(char str[], int offset, int len) {
-        if (len > 0)                // let arraycopy report AIOOBE for len < 0
-            ensureCapacityInternal(count + len);
-        System.arraycopy(str, offset, value, count, len);
-        count += len;
+        int end = offset + len;
+        checkRange(offset, end, str.length);
+        ensureCapacityInternal(count + len);
+        appendChars(str, offset, end);
         return this;
     }
 
@@ -592,20 +654,39 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder append(boolean b) {
-        if (b) {
-            ensureCapacityInternal(count + 4);
-            value[count++] = 't';
-            value[count++] = 'r';
-            value[count++] = 'u';
-            value[count++] = 'e';
+        ensureCapacityInternal(count + (b ? 4 : 5));
+        int count = this.count;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            if (b) {
+                val[count++] = 't';
+                val[count++] = 'r';
+                val[count++] = 'u';
+                val[count++] = 'e';
+            } else {
+                val[count++] = 'f';
+                val[count++] = 'a';
+                val[count++] = 'l';
+                val[count++] = 's';
+                val[count++] = 'e';
+            }
         } else {
-            ensureCapacityInternal(count + 5);
-            value[count++] = 'f';
-            value[count++] = 'a';
-            value[count++] = 'l';
-            value[count++] = 's';
-            value[count++] = 'e';
+            if (b) {
+                checkOffset(count + 4, val.length >> 1);
+                StringUTF16.putChar(val, count++, 't');
+                StringUTF16.putChar(val, count++, 'r');
+                StringUTF16.putChar(val, count++, 'u');
+                StringUTF16.putChar(val, count++, 'e');
+            } else {
+                checkOffset(count + 5, val.length >> 1);
+                StringUTF16.putChar(val, count++, 'f');
+                StringUTF16.putChar(val, count++, 'a');
+                StringUTF16.putChar(val, count++, 'l');
+                StringUTF16.putChar(val, count++, 's');
+                StringUTF16.putChar(val, count++, 'e');
+            }
         }
+        this.count = count;
         return this;
     }
 
@@ -627,7 +708,14 @@
     @Override
     public AbstractStringBuilder append(char c) {
         ensureCapacityInternal(count + 1);
-        value[count++] = c;
+        if (isLatin1() && StringLatin1.canEncode(c)) {
+            value[count++] = (byte)c;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, count++, c);
+        }
         return this;
     }
 
@@ -652,7 +740,13 @@
                                      : Integer.stringSize(i);
         int spaceNeeded = count + appendedLength;
         ensureCapacityInternal(spaceNeeded);
-        Integer.getChars(i, spaceNeeded, value);
+        if (isLatin1()) {
+            Integer.getChars(i, spaceNeeded, value);
+        } else {
+            byte[] val = this.value;
+            checkOffset(spaceNeeded, val.length >> 1);
+            Integer.getCharsUTF16(i, spaceNeeded, val);
+        }
         count = spaceNeeded;
         return this;
     }
@@ -678,7 +772,13 @@
                                      : Long.stringSize(l);
         int spaceNeeded = count + appendedLength;
         ensureCapacityInternal(spaceNeeded);
-        Long.getChars(l, spaceNeeded, value);
+        if (isLatin1()) {
+            Long.getChars(l, spaceNeeded, value);
+        } else {
+            byte[] val = this.value;
+            checkOffset(spaceNeeded, val.length >> 1);
+            Long.getCharsUTF16(l, spaceNeeded, val);
+        }
         count = spaceNeeded;
         return this;
     }
@@ -732,15 +832,13 @@
      *             greater than {@code end}.
      */
     public AbstractStringBuilder delete(int start, int end) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (end > count)
+        if (end > count) {
             end = count;
-        if (start > end)
-            throw new StringIndexOutOfBoundsException();
+        }
+        checkRangeSIOOBE(start, end, count);
         int len = end - start;
         if (len > 0) {
-            System.arraycopy(value, start+len, value, start, count-end);
+            shift(end, -len);
             count -= len;
         }
         return this;
@@ -766,20 +864,10 @@
      * {@code codePoint} isn't a valid Unicode code point
      */
     public AbstractStringBuilder appendCodePoint(int codePoint) {
-        final int count = this.count;
-
         if (Character.isBmpCodePoint(codePoint)) {
-            ensureCapacityInternal(count + 1);
-            value[count] = (char) codePoint;
-            this.count = count + 1;
-        } else if (Character.isValidCodePoint(codePoint)) {
-            ensureCapacityInternal(count + 2);
-            Character.toSurrogates(codePoint, value, count);
-            this.count = count + 2;
-        } else {
-            throw new IllegalArgumentException();
+            return append((char)codePoint);
         }
-        return this;
+        return append(Character.toChars(codePoint));
     }
 
     /**
@@ -800,9 +888,8 @@
      *              {@code length()}.
      */
     public AbstractStringBuilder deleteCharAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        System.arraycopy(value, index+1, value, index, count-index-1);
+        checkIndex(index, count);
+        shift(index + 1, -1);
         count--;
         return this;
     }
@@ -827,22 +914,16 @@
      *             greater than {@code end}.
      */
     public AbstractStringBuilder replace(int start, int end, String str) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (start > count)
-            throw new StringIndexOutOfBoundsException("start > length()");
-        if (start > end)
-            throw new StringIndexOutOfBoundsException("start > end");
-
-        if (end > count)
+        if (end > count) {
             end = count;
+        }
+        checkRangeSIOOBE(start, end, count);
         int len = str.length();
         int newCount = count + len - (end - start);
         ensureCapacityInternal(newCount);
-
-        System.arraycopy(value, end, value, start + len, count - end);
-        str.getChars(value, start);
+        shift(end, newCount - count);
         count = newCount;
+        putStringAt(start, str);
         return this;
     }
 
@@ -907,13 +988,16 @@
      *             greater than {@code end}.
      */
     public String substring(int start, int end) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (end > count)
-            throw new StringIndexOutOfBoundsException(end);
-        if (start > end)
-            throw new StringIndexOutOfBoundsException(end - start);
-        return new String(value, start, end - start);
+        checkRangeSIOOBE(start, end, count);
+        if (isLatin1()) {
+            return StringLatin1.newString(value, start, end - start);
+        }
+        return StringUTF16.newStringSB(value, start, end - start);
+    }
+
+    private void shift(int offset, int n) {
+        System.arraycopy(value, offset << coder,
+                         value, (offset + n) << coder, (count - offset) << coder);
     }
 
     /**
@@ -940,16 +1024,12 @@
     public AbstractStringBuilder insert(int index, char[] str, int offset,
                                         int len)
     {
-        if ((index < 0) || (index > length()))
-            throw new StringIndexOutOfBoundsException(index);
-        if ((offset < 0) || (len < 0) || (offset > str.length - len))
-            throw new StringIndexOutOfBoundsException(
-                "offset " + offset + ", len " + len + ", str.length "
-                + str.length);
+        checkOffset(index, count);
+        checkRangeSIOOBE(offset, offset + len, str.length);
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, index, value, index + len, count - index);
-        System.arraycopy(str, offset, value, index, len);
+        shift(index, len);
         count += len;
+        putCharsAt(index, str, offset, offset + len);
         return this;
     }
 
@@ -1008,15 +1088,15 @@
      * @throws     StringIndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, String str) {
-        if ((offset < 0) || (offset > length()))
-            throw new StringIndexOutOfBoundsException(offset);
-        if (str == null)
+        checkOffset(offset, count);
+        if (str == null) {
             str = "null";
+        }
         int len = str.length();
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, offset, value, offset + len, count - offset);
-        str.getChars(value, offset);
+        shift(offset, len);
         count += len;
+        putStringAt(offset, str);
         return this;
     }
 
@@ -1045,13 +1125,12 @@
      * @throws     StringIndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, char[] str) {
-        if ((offset < 0) || (offset > length()))
-            throw new StringIndexOutOfBoundsException(offset);
+        checkOffset(offset, count);
         int len = str.length;
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, offset, value, offset + len, count - offset);
-        System.arraycopy(str, 0, value, offset, len);
+        shift(offset, len);
         count += len;
+        putCharsAt(offset, str, 0, len);
         return this;
     }
 
@@ -1077,10 +1156,12 @@
      * @throws     IndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
-        if (s == null)
+        if (s == null) {
             s = "null";
-        if (s instanceof String)
+        }
+        if (s instanceof String) {
             return this.insert(dstOffset, (String)s);
+        }
         return this.insert(dstOffset, s, 0, s.length());
     }
 
@@ -1128,23 +1209,19 @@
      *              {@code start} is greater than {@code end} or
      *              {@code end} is greater than {@code s.length()}
      */
-     public AbstractStringBuilder insert(int dstOffset, CharSequence s,
-                                         int start, int end) {
-        if (s == null)
+    public AbstractStringBuilder insert(int dstOffset, CharSequence s,
+                                        int start, int end)
+    {
+        if (s == null) {
             s = "null";
-        if ((dstOffset < 0) || (dstOffset > this.length()))
-            throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
-        if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
-            throw new IndexOutOfBoundsException(
-                "start " + start + ", end " + end + ", s.length() "
-                + s.length());
+        }
+        checkOffset(dstOffset, count);
+        checkRange(start, end, s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, dstOffset, value, dstOffset + len,
-                         count - dstOffset);
-        for (int i=start; i<end; i++)
-            value[dstOffset++] = s.charAt(i);
+        shift(dstOffset, len);
         count += len;
+        putCharsAt(dstOffset, s, start, end);
         return this;
     }
 
@@ -1191,10 +1268,18 @@
      * @throws     IndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, char c) {
+        checkOffset(offset, count);
         ensureCapacityInternal(count + 1);
-        System.arraycopy(value, offset, value, offset + 1, count - offset);
-        value[offset] = c;
+        shift(offset, 1);
         count += 1;
+        if (isLatin1() && StringLatin1.canEncode(c)) {
+            value[offset] = (byte)c;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, offset, c);
+        }
         return this;
     }
 
@@ -1326,7 +1411,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count, str, fromIndex);
+        return String.indexOf(value, coder, count, str, fromIndex);
     }
 
     /**
@@ -1366,7 +1451,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count, str, fromIndex);
+        return String.lastIndexOf(value, coder, count, str, fromIndex);
     }
 
     /**
@@ -1392,34 +1477,47 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder reverse() {
-        boolean hasSurrogates = false;
+        byte[] val = this.value;
+        int count = this.count;
+        int coder = this.coder;
         int n = count - 1;
-        for (int j = (n-1) >> 1; j >= 0; j--) {
-            int k = n - j;
-            char cj = value[j];
-            char ck = value[k];
-            value[j] = ck;
-            value[k] = cj;
-            if (Character.isSurrogate(cj) ||
-                Character.isSurrogate(ck)) {
-                hasSurrogates = true;
+        if (COMPACT_STRINGS && coder == LATIN1) {
+            for (int j = (n-1) >> 1; j >= 0; j--) {
+                int k = n - j;
+                byte cj = val[j];
+                val[j] = val[k];
+                val[k] = cj;
             }
-        }
-        if (hasSurrogates) {
-            reverseAllValidSurrogatePairs();
+        } else {
+            checkOffset(count, val.length >> 1);
+            boolean hasSurrogates = false;
+            for (int j = (n-1) >> 1; j >= 0; j--) {
+                int k = n - j;
+                char cj = StringUTF16.getChar(val, j);
+                char ck = StringUTF16.getChar(val, k);
+                StringUTF16.putChar(val, j, ck);
+                StringUTF16.putChar(val, k, cj);
+                if (Character.isSurrogate(cj) ||
+                    Character.isSurrogate(ck)) {
+                    hasSurrogates = true;
+                }
+            }
+            if (hasSurrogates) {
+                reverseAllValidSurrogatePairs(val, count);
+            }
         }
         return this;
     }
 
     /** Outlined helper method for reverse() */
-    private void reverseAllValidSurrogatePairs() {
+    private void reverseAllValidSurrogatePairs(byte[] val, int count) {
         for (int i = 0; i < count - 1; i++) {
-            char c2 = value[i];
+            char c2 = StringUTF16.getChar(val, i);
             if (Character.isLowSurrogate(c2)) {
-                char c1 = value[i + 1];
+                char c1 = StringUTF16.getChar(val, i + 1);
                 if (Character.isHighSurrogate(c1)) {
-                    value[i++] = c1;
-                    value[i] = c2;
+                    StringUTF16.putChar(val, i++, c1);
+                    StringUTF16.putChar(val, i, c2);
                 }
             }
         }
@@ -1444,10 +1542,13 @@
      */
     @Override
     public IntStream chars() {
+        byte[] val = this.value; int count = this.count; byte coder = this.coder;
+        checkOffset(count, val.length >> coder);
         // 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),
+                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                                      : new StringUTF16.CharsSpliterator(val, 0, count, 0),
                 Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                 false);
     }
@@ -1458,10 +1559,13 @@
      */
     @Override
     public IntStream codePoints() {
+        byte[] val = this.value; int count = this.count; byte coder = this.coder;
+        checkOffset(count, val.length >> coder);
         // 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),
+                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                                      : new StringUTF16.CodePointsSpliterator(val, 0, count, 0),
                 Spliterator.ORDERED,
                 false);
     }
@@ -1469,8 +1573,147 @@
     /**
      * Needed by {@code String} for the contentEquals method.
      */
-    final char[] getValue() {
+    final byte[] getValue() {
         return value;
     }
 
+    /*
+     * Invoker guarantees it is in UTF16 (inflate itself for asb), if two
+     * coders are different and the dstBegin has enough space
+     *
+     * @param dstBegin  the char index, not offset of byte[]
+     * @param coder     the coder of dst[]
+     */
+    protected void getBytes(byte dst[], int dstBegin, byte coder) {
+        if (this.coder == coder) {
+            System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
+        } else {        // this.coder == LATIN && coder == UTF16
+            StringLatin1.inflateSB(value, dst, dstBegin, count);
+        }
+    }
+
+    /* for readObject() */
+    protected void initBytes(char[] value, int off, int len) {
+        if (String.COMPACT_STRINGS) {
+            this.value = StringUTF16.compress(value, off, len);
+            if (this.value != null) {
+                this.coder = LATIN1;
+                return;
+            }
+        }
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(value, off, len);
+    }
+
+    final byte getCoder() {
+        return COMPACT_STRINGS ? coder : UTF16;
+    }
+
+    final boolean isLatin1() {
+        return COMPACT_STRINGS && coder == LATIN1;
+    }
+
+    private final void putCharsAt(int index, char[] s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = index; i < end; i++) {
+                char c = s[i];
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, index, s, off, end);
+        }
+    }
+
+    private final void putCharsAt(int index, CharSequence s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = index; i < end; i++) {
+                char c = s.charAt(i);
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, index, s, off, end);
+        }
+    }
+
+    private final void putStringAt(int index, String str) {
+        if (getCoder() != str.coder()) {
+            inflate();
+        }
+        byte[] val = this.value;
+        byte coder = this.coder;
+        checkOffset(index + str.length(), val.length >> coder);
+        str.getBytes(val, index, coder);
+    }
+
+    private final void appendChars(char[] s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = count; i < end; i++) {
+                char c = s[i];
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    count = j;
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    count += end - i;
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, count, s, off, end);
+        }
+        count += end - off;
+    }
+
+    private final void appendChars(CharSequence s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = count; i < end; i++) {
+                char c = s.charAt(i);
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    count = j;
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    count += end - i;
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, count, s, off, end);
+        }
+        count += end - off;
+    }
+
+    /* IndexOutOfBoundsException, if out of bounds */
+    private static void checkRange(int start, int end, int len) {
+        if (start < 0 || start > end || end > len) {
+            throw new IndexOutOfBoundsException(
+                "start " + start + ", end " + end + ", length " + len);
+        }
+    }
+
+    /* StringIndexOutOfBoundsException, if out of bounds */
+    private static void checkRangeSIOOBE(int start, int end, int len) {
+        if (start < 0 || start > end || end > len) {
+            throw new StringIndexOutOfBoundsException(
+                "start " + start + ", end " + end + ", length " + len);
+        }
+    }
 }
--- a/src/java.base/share/classes/java/lang/Class.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Class.java	Thu Nov 12 14:15:05 2015 -0800
@@ -55,7 +55,7 @@
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.StringJoiner;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.reflect.CallerSensitive;
 import sun.reflect.ConstantPool;
--- a/src/java.base/share/classes/java/lang/Integer.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Integer.java	Thu Nov 12 14:15:05 2015 -0800
@@ -29,6 +29,10 @@
 import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+
 /**
  * The {@code Integer} class wraps a value of the primitive type
  * {@code int} in an object. An object of type {@code Integer}
@@ -138,25 +142,47 @@
             return toString(i);
         }
 
-        char buf[] = new char[33];
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[33];
+            boolean negative = (i < 0);
+            int charPos = 32;
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)digits[-(i % radix)];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)digits[-i];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+
+            return StringLatin1.newString(buf, charPos, (33 - charPos));
+        }
+        return toStringUTF16(i, radix);
+    }
+
+    private static String toStringUTF16(int i, int radix) {
+        byte[] buf = new byte[33 * 2];
         boolean negative = (i < 0);
         int charPos = 32;
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = digits[-(i % radix)];
+            StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
             i = i / radix;
         }
-        buf[charPos] = digits[-i];
+        StringUTF16.putChar(buf, charPos, digits[-i]);
 
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (33 - charPos));
+        return StringUTF16.newString(buf, charPos, (33 - charPos));
     }
 
     /**
@@ -312,12 +338,16 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedInt(val, shift, buf, 0, chars);
-
-        // Use special constructor which takes over "buf".
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[chars];
+            formatUnsignedInt(val, shift, buf, 0, chars);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedIntUTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -331,7 +361,7 @@
      * @param offset the offset in the destination buffer to start at
      * @param len the number of characters to write
      */
-     static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
+    static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         // assert offset >= 0 && offset < buf.length : "illegal offset";
         // assert len > 0 && (offset + len) <= buf.length : "illegal length";
@@ -344,6 +374,28 @@
         } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[val & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    /** byte[]/UTF16 version    */
+    static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
     static final char [] DigitTens = {
         '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
         '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
@@ -401,9 +453,15 @@
         if (i == Integer.MIN_VALUE)
             return "-2147483648";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            getCharsUTF16(i, size, buf);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -433,7 +491,7 @@
      *
      * Will fail if i == Integer.MIN_VALUE
      */
-    static void getChars(int i, int index, char[] buf) {
+    static void getChars(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
         char sign = 0;
@@ -449,8 +507,8 @@
         // really: r = i - (q * 100);
             r = i - ((q << 6) + (q << 5) + (q << 2));
             i = q;
-            buf [--charPos] = DigitOnes[r];
-            buf [--charPos] = DigitTens[r];
+            buf [--charPos] = (byte)DigitOnes[r];
+            buf [--charPos] = (byte)DigitTens[r];
         }
 
         // Fall thru to fast mode for smaller numbers
@@ -458,12 +516,46 @@
         for (;;) {
             q = (i * 52429) >>> (16+3);
             r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
-            buf [--charPos] = digits [r];
+            buf [--charPos] = (byte)digits [r];
             i = q;
             if (i == 0) break;
         }
         if (sign != 0) {
-            buf [--charPos] = sign;
+            buf [--charPos] = (byte)sign;
+        }
+    }
+
+    static void getCharsUTF16(int i, int index, byte[] buf) {
+        int q, r;
+        int charPos = index;
+        char sign = 0;
+
+        if (i < 0) {
+            sign = '-';
+            i = -i;
+        }
+
+        // Generate two digits per iteration
+        while (i >= 65536) {
+            q = i / 100;
+        // really: r = i - (q * 100);
+            r = i - ((q << 6) + (q << 5) + (q << 2));
+            i = q;
+            StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, DigitTens[r]);
+        }
+
+        // Fall thru to fast mode for smaller numbers
+        // assert(i <= 65536, i);
+        for (;;) {
+            q = (i * 52429) >>> (16+3);
+            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
+            StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
+            i = q;
+            if (i == 0) break;
+        }
+        if (sign != 0) {
+            StringUTF16.putChar(buf, --charPos, sign);
         }
     }
 
--- a/src/java.base/share/classes/java/lang/Long.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Long.java	Thu Nov 12 14:15:05 2015 -0800
@@ -30,6 +30,9 @@
 import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
 
 /**
  * The {@code Long} class wraps a value of the primitive type {@code
@@ -124,25 +127,46 @@
             radix = 10;
         if (radix == 10)
             return toString(i);
-        char[] buf = new char[65];
+
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[65];
+            int charPos = 64;
+            boolean negative = (i < 0);
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)Integer.digits[(int)(-i)];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+            return StringLatin1.newString(buf, charPos, (65 - charPos));
+        }
+        return toStringUTF16(i, radix);
+    }
+
+    private static String toStringUTF16(long i, int radix) {
+        byte[] buf = new byte[65 * 2];
         int charPos = 64;
         boolean negative = (i < 0);
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = Integer.digits[(int)(-(i % radix))];
+            StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
             i = i / radix;
         }
-        buf[charPos] = Integer.digits[(int)(-i)];
-
+        StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (65 - charPos));
+        return StringUTF16.newString(buf, charPos, (65 - charPos));
     }
 
     /**
@@ -355,10 +379,16 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedLong(val, shift, buf, 0, chars);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[chars];
+            formatUnsignedLong0(val, shift, buf, 0, chars);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedLong0UTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -385,6 +415,28 @@
         } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    /** byte[]/UTF16 version    */
+    static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
     /**
      * Returns a {@code String} object representing the specified
      * {@code long}.  The argument is converted to signed decimal
@@ -399,9 +451,15 @@
         if (i == Long.MIN_VALUE)
             return "-9223372036854775808";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            getCharsUTF16(i, size, buf);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -431,7 +489,7 @@
      *
      * Will fail if i == Long.MIN_VALUE
      */
-    static void getChars(long i, int index, char[] buf) {
+    static void getChars(long i, int index, byte[] buf) {
         long q;
         int r;
         int charPos = index;
@@ -448,8 +506,8 @@
             // really: r = i - (q * 100);
             r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
             i = q;
-            buf[--charPos] = Integer.DigitOnes[r];
-            buf[--charPos] = Integer.DigitTens[r];
+            buf[--charPos] = (byte)Integer.DigitOnes[r];
+            buf[--charPos] = (byte)Integer.DigitTens[r];
         }
 
         // Get 2 digits/iteration using ints
@@ -460,8 +518,8 @@
             // really: r = i2 - (q * 100);
             r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
             i2 = q2;
-            buf[--charPos] = Integer.DigitOnes[r];
-            buf[--charPos] = Integer.DigitTens[r];
+            buf[--charPos] = (byte)Integer.DigitOnes[r];
+            buf[--charPos] = (byte)Integer.DigitTens[r];
         }
 
         // Fall thru to fast mode for smaller numbers
@@ -469,12 +527,59 @@
         for (;;) {
             q2 = (i2 * 52429) >>> (16+3);
             r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
-            buf[--charPos] = Integer.digits[r];
+            buf[--charPos] = (byte)Integer.digits[r];
             i2 = q2;
             if (i2 == 0) break;
         }
         if (sign != 0) {
-            buf[--charPos] = sign;
+            buf[--charPos] = (byte)sign;
+        }
+    }
+
+    static void getCharsUTF16(long i, int index, byte[] buf) {
+        long q;
+        int r;
+        int charPos = index;
+        char sign = 0;
+
+        if (i < 0) {
+            sign = '-';
+            i = -i;
+        }
+
+        // Get 2 digits/iteration using longs until quotient fits into an int
+        while (i > Integer.MAX_VALUE) {
+            q = i / 100;
+            // really: r = i - (q * 100);
+            r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
+            i = q;
+            StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
+        }
+
+        // Get 2 digits/iteration using ints
+        int q2;
+        int i2 = (int)i;
+        while (i2 >= 65536) {
+            q2 = i2 / 100;
+            // really: r = i2 - (q * 100);
+            r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
+            i2 = q2;
+            StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
+        }
+
+        // Fall thru to fast mode for smaller numbers
+        // assert(i2 <= 65536, i2);
+        for (;;) {
+            q2 = (i2 * 52429) >>> (16+3);
+            r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
+            StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
+            i2 = q2;
+            if (i2 == 0) break;
+        }
+        if (sign != 0) {
+            StringUTF16.putChar(buf, --charPos, sign);
         }
     }
 
--- a/src/java.base/share/classes/java/lang/Process.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Process.java	Thu Nov 12 14:15:05 2015 -0800
@@ -83,7 +83,7 @@
  * {@link #getPid() process id},
  * {@link #info() information about the process},
  * {@link #children() direct children}, and
- * {@link #allChildren() direct and indirect children} of the process.
+ * {@link #descendants() direct children plus descendants of those children} of the process.
  * Delegating to the underlying Process or ProcessHandle is typically
  * easiest and most efficient.
  *
@@ -351,7 +351,7 @@
      * The {@link java.util.concurrent.CompletableFuture} provides the ability
      * to trigger dependent functions or actions that may be run synchronously
      * or asynchronously upon process termination.
-     * When the process terminates the CompletableFuture is
+     * When the process has terminated the CompletableFuture is
      * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
      * of the exit status of the process.
      * <p>
@@ -362,9 +362,6 @@
      * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
      * the CompletableFuture does not affect the Process.
      * <p>
-     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
-     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
-     * <p>
      * Processes returned from {@link ProcessBuilder#start} override the
      * default implementation to provide an efficient mechanism to wait
      * for process exit.
@@ -406,6 +403,9 @@
      *       return delegate.onExit().thenApply(p -> this);
      *    }
      * }</pre>
+     * @apiNote
+     * The process may be observed to have terminated with {@link #isAlive}
+     * before the ComputableFuture is completed and dependent actions are invoked.
      *
      * @return a new {@code CompletableFuture<Process>} for the Process
      *
@@ -464,7 +464,7 @@
      * {@link java.lang.UnsupportedOperationException} and performs no other action.
      * Subclasses should override this method to provide a ProcessHandle for the
      * process.  The methods {@link #getPid}, {@link #info}, {@link #children},
-     * and {@link #allChildren}, unless overridden, operate on the ProcessHandle.
+     * and {@link #descendants}, unless overridden, operate on the ProcessHandle.
      *
      * @return Returns a ProcessHandle for the Process
      * @throws UnsupportedOperationException if the Process implementation
@@ -481,9 +481,8 @@
     /**
      * Returns a snapshot of information about the process.
      *
-     * <p> An {@link ProcessHandle.Info} instance has various accessor methods
-     * that return information about the process, if the process is alive and
-     * the information is available, otherwise {@code null} is returned.
+     * <p> A {@link ProcessHandle.Info} instance has accessor methods
+     * that return information about the process if it is available.
      *
      * @implSpec
      * This implementation returns information about the process as:
@@ -524,9 +523,9 @@
     }
 
     /**
-     * Returns a snapshot of the direct and indirect children of the process.
-     * An indirect child is one whose parent is either a direct child or
-     * another indirect child.
+     * Returns a snapshot of the descendants of the process.
+     * The descendants of a process are the children of the process
+     * plus the descendants of those children, recursively.
      * Typically, a process that is {@link #isAlive not alive} has no children.
      * <p>
      * <em>Note that processes are created and terminate asynchronously.
@@ -535,18 +534,18 @@
      *
      * @implSpec
      * This implementation returns all children as:
-     * {@link #toHandle toHandle().allChildren()}.
+     * {@link #toHandle toHandle().descendants()}.
      *
-     * @return a sequential Stream of ProcessHandles for processes that are
-     *         direct and indirect children of the process
+     * @return a sequential Stream of ProcessHandles for processes that
+     *         are descendants of the process
      * @throws UnsupportedOperationException if the Process implementation
      *         does not support this operation
      * @throws SecurityException if a security manager has been installed and
      *         it denies RuntimePermission("manageProcess")
      * @since 1.9
      */
-    public Stream<ProcessHandle> allChildren() {
-        return toHandle().allChildren();
+    public Stream<ProcessHandle> descendants() {
+        return toHandle().descendants();
     }
 
 
--- a/src/java.base/share/classes/java/lang/ProcessHandle.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ProcessHandle.java	Thu Nov 12 14:15:05 2015 -0800
@@ -54,7 +54,7 @@
  * Each ProcessHandle identifies and allows control of a process in the native
  * system. ProcessHandles are returned from the factory methods {@link #current()},
  * {@link #of(long)},
- * {@link #children}, {@link #allChildren}, {@link #parent()} and
+ * {@link #children}, {@link #descendants}, {@link #parent()} and
  * {@link #allProcesses()}.
  * <p>
  * The {@link Process} instances created by {@link ProcessBuilder} can be queried
@@ -164,21 +164,21 @@
     Stream<ProcessHandle> children();
 
     /**
-     * Returns a snapshot of the current direct and indirect children of the process.
-     * An indirect child is one whose parent is either a direct child or
-     * another indirect child.
+     * Returns a snapshot of the descendants of the process.
+     * The descendants of a process are the children of the process
+     * plus the descendants of those children, recursively.
      * Typically, a process that is {@link #isAlive not alive} has no children.
      * <p>
      * <em>Note that processes are created and terminate asynchronously.
      * There is no guarantee that a process is {@link #isAlive alive}.
      * </em>
      *
-     * @return a sequential Stream of ProcessHandles for processes that are
-     *         direct and indirect children of the process
+     * @return a sequential Stream of ProcessHandles for processes that
+     *         are descendants of the process
      * @throws SecurityException if a security manager has been installed and
      *         it denies RuntimePermission("manageProcess")
      */
-    Stream<ProcessHandle> allChildren();
+    Stream<ProcessHandle> descendants();
 
     /**
      * Returns a snapshot of all processes visible to the current process.
@@ -201,9 +201,8 @@
     /**
      * Returns a snapshot of information about the process.
      *
-     * <p> An {@code Info} instance has various accessor methods that return
-     * information about the process, if the process is alive and the
-     * information is available.
+     * <p> A {@link ProcessHandle.Info} instance has accessor methods that return
+     * information about the process if it is available.
      *
      * @return a snapshot of information about the process, always non-null
      */
@@ -288,7 +287,7 @@
      * The {@link java.util.concurrent.CompletableFuture} provides the ability
      * to trigger dependent functions or actions that may be run synchronously
      * or asynchronously upon process termination.
-     * When the process terminates the CompletableFuture is
+     * When the process has terminated the CompletableFuture is
      * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
      * of the exit status of the process.
      * The {@code onExit} method can be called multiple times to invoke
@@ -300,9 +299,9 @@
      * {@link java.util.concurrent.Future#get() wait} for it to terminate.
      * {@link java.util.concurrent.Future#cancel(boolean) Cancelling}
      * the CompleteableFuture does not affect the Process.
-     * <p>
-     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
-     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
+     * @apiNote
+     * The process may be observed to have terminated with {@link #isAlive}
+     * before the ComputableFuture is completed and dependent actions are invoked.
      *
      * @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle
      *
--- a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Thu Nov 12 14:15:05 2015 -0800
@@ -389,7 +389,7 @@
     }
 
     @Override
-    public Stream<ProcessHandle> allChildren() {
+    public Stream<ProcessHandle> descendants() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission("manageProcess"));
--- a/src/java.base/share/classes/java/lang/String.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/String.java	Thu Nov 12 14:15:05 2015 -0800
@@ -36,7 +36,6 @@
 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;
@@ -119,8 +118,19 @@
 
 public final class String
     implements java.io.Serializable, Comparable<String>, CharSequence {
+
     /** The value is used for character storage. */
-    private final char value[];
+    private final byte[] value;
+
+    /**
+     * The identifier of the encoding used to encode the bytes in
+     * {@code value}. The supported values in this implementation are
+     *
+     * LATIN1
+     * UTF16
+     *
+     */
+    private final byte coder;
 
     /** Cache the hash code for the string */
     private int hash; // Default to 0
@@ -129,6 +139,49 @@
     private static final long serialVersionUID = -6849794470754667710L;
 
     /**
+     * If String compaction is disabled, the bytes in {@code value} are
+     * always encoded in UTF16.
+     *
+     * For methods with several possible implementation paths, when String
+     * compaction is disabled, only one code path is taken.
+     *
+     * The instance field value is generally opaque to optimizing JIT
+     * compilers. Therefore, in performance-sensitive place, an explicit
+     * check of the static boolean {@code COMPACT_STRINGS} is done first
+     * before checking the {@code coder} field since the static boolean
+     * {@code COMPACT_STRINGS} would be constant folded away by an
+     * optimizing JIT compiler. The idioms for these cases are as follows.
+     *
+     * For code such as:
+     *
+     *    if (coder == LATIN1) { ... }
+     *
+     * can be written more optimally as
+     *
+     *    if (coder() == LATIN1) { ... }
+     *
+     * or:
+     *
+     *    if (COMPACT_STRINGS && coder == LATIN1) { ... }
+     *
+     * An optimizing JIT compiler can fold the above conditional as:
+     *
+     *    COMPACT_STRINGS == true  => if (coder == LATIN1) { ... }
+     *    COMPACT_STRINGS == false => if (false)           { ... }
+     *
+     * @implNote
+     * The actual value for this field is injected by JVM. The static
+     * initialization block is used to set the value here to communicate
+     * that this static final field is not statically foldable, and to
+     * avoid any possible circular dependency during vm initialization.
+     */
+    static final boolean COMPACT_STRINGS;
+
+    static {
+        COMPACT_STRINGS = true;
+    }
+
+    /**
      * Class String is special cased within the Serialization Stream Protocol.
      *
      * A String instance is written into an ObjectOutputStream according to
@@ -145,6 +198,7 @@
      */
     public String() {
         this.value = "".value;
+        this.coder = "".coder;
     }
 
     /**
@@ -160,6 +214,7 @@
     @HotSpotIntrinsicCandidate
     public String(String original) {
         this.value = original.value;
+        this.coder = original.coder;
         this.hash = original.hash;
     }
 
@@ -173,7 +228,7 @@
      *         The initial value of the string
      */
     public String(char value[]) {
-        this.value = Arrays.copyOf(value, value.length);
+        this(value, 0, value.length, null);
     }
 
     /**
@@ -198,23 +253,12 @@
      *          {@code offset} is greater than {@code value.length - count}
      */
     public String(char value[], int offset, int count) {
-        if (offset < 0) {
-            throw new StringIndexOutOfBoundsException(offset);
-        }
-        if (count <= 0) {
-            if (count < 0) {
-                throw new StringIndexOutOfBoundsException(count);
-            }
-            if (offset <= value.length) {
-                this.value = "".value;
-                return;
-            }
-        }
-        // Note: offset or count might be near -1>>>1.
-        if (offset > value.length - count) {
-            throw new StringIndexOutOfBoundsException(offset + count);
-        }
-        this.value = Arrays.copyOfRange(value, offset, offset + count);
+        this(value, offset, count, rangeCheck(value, offset, count));
+    }
+
+    private static Void rangeCheck(char[] value, int offset, int count) {
+        checkBoundsOffCount(offset, count, value.length);
+        return null;
     }
 
     /**
@@ -246,48 +290,22 @@
      * @since  1.5
      */
     public String(int[] codePoints, int offset, int count) {
-        if (offset < 0) {
-            throw new StringIndexOutOfBoundsException(offset);
+        checkBoundsOffCount(offset, count, codePoints.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
         }
-        if (count <= 0) {
-            if (count < 0) {
-                throw new StringIndexOutOfBoundsException(count);
-            }
-            if (offset <= codePoints.length) {
-                this.value = "".value;
+        if (COMPACT_STRINGS) {
+            byte[] val = StringLatin1.toBytes(codePoints, offset, count);
+            if (val != null) {
+                this.coder = LATIN1;
+                this.value = val;
                 return;
             }
         }
-        // Note: offset or count might be near -1>>>1.
-        if (offset > codePoints.length - count) {
-            throw new StringIndexOutOfBoundsException(offset + count);
-        }
-
-        final int end = offset + count;
-
-        // Pass 1: Compute precise size of char[]
-        int n = count;
-        for (int i = offset; i < end; i++) {
-            int c = codePoints[i];
-            if (Character.isBmpCodePoint(c))
-                continue;
-            else if (Character.isValidCodePoint(c))
-                n++;
-            else throw new IllegalArgumentException(Integer.toString(c));
-        }
-
-        // Pass 2: Allocate and fill in char[]
-        final char[] v = new char[n];
-
-        for (int i = offset, j = 0; i < end; i++, j++) {
-            int c = codePoints[i];
-            if (Character.isBmpCodePoint(c))
-                v[j] = (char)c;
-            else
-                Character.toSurrogates(c, v, j++);
-        }
-
-        this.value = v;
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(codePoints, offset, count);
     }
 
     /**
@@ -332,20 +350,24 @@
      */
     @Deprecated
     public String(byte ascii[], int hibyte, int offset, int count) {
-        checkBounds(ascii, offset, count);
-        char[] value = new char[count];
-
-        if (hibyte == 0) {
-            for (int i = count; i-- > 0;) {
-                value[i] = (char)(ascii[i + offset] & 0xff);
-            }
+        checkBoundsOffCount(offset, count, ascii.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS && (byte)hibyte == 0) {
+            this.value = Arrays.copyOfRange(ascii, offset, offset + count);
+            this.coder = LATIN1;
         } else {
             hibyte <<= 8;
-            for (int i = count; i-- > 0;) {
-                value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
+            byte[] val = StringUTF16.newBytesFor(count);
+            for (int i = 0; i < count; i++) {
+                StringUTF16.putChar(val, i, hibyte | (ascii[offset++] & 0xff));
             }
+            this.value = val;
+            this.coder = UTF16;
         }
-        this.value = value;
     }
 
     /**
@@ -383,19 +405,6 @@
         this(ascii, hibyte, 0, ascii.length);
     }
 
-    /* Common private utility method used to bounds check the byte array
-     * and requested offset & length values used by the String(byte[],..)
-     * constructors.
-     */
-    private static void checkBounds(byte[] bytes, int offset, int length) {
-        if (length < 0)
-            throw new StringIndexOutOfBoundsException(length);
-        if (offset < 0)
-            throw new StringIndexOutOfBoundsException(offset);
-        if (offset > bytes.length - length)
-            throw new StringIndexOutOfBoundsException(offset + length);
-    }
-
     /**
      * Constructs a new {@code String} by decoding the specified subarray of
      * bytes using the specified charset.  The length of the new {@code String}
@@ -433,8 +442,11 @@
             throws UnsupportedEncodingException {
         if (charsetName == null)
             throw new NullPointerException("charsetName");
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(charsetName, bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charsetName, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -470,8 +482,11 @@
     public String(byte bytes[], int offset, int length, Charset charset) {
         if (charset == null)
             throw new NullPointerException("charset");
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(charset, bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charset, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -553,8 +568,10 @@
      * @since  1.1
      */
     public String(byte bytes[], int offset, int length) {
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret = StringCoding.decode(bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -587,9 +604,7 @@
      *         A {@code StringBuffer}
      */
     public String(StringBuffer buffer) {
-        synchronized(buffer) {
-            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
-        }
+        this(buffer.toString());
     }
 
     /**
@@ -608,18 +623,20 @@
      * @since  1.5
      */
     public String(StringBuilder builder) {
-        this.value = Arrays.copyOf(builder.getValue(), builder.length());
+        this(builder, null);
     }
 
-    /*
+   /*
     * Package private constructor which shares value array for speed.
     * this constructor is always expected to be called with share==true.
     * a separate constructor is needed because we already have a public
     * String(char[]) constructor that makes a copy of the given char[].
     */
-    String(char[] value, boolean share) {
+    // TBD: this is kept for package internal use (Thread/System),
+    // should be removed if they all have a byte[] version
+    String(char[] val, boolean share) {
         // assert share : "unshared not supported";
-        this.value = value;
+        this(val, 0, val.length, null);
     }
 
     /**
@@ -631,7 +648,7 @@
      *          object.
      */
     public int length() {
-        return value.length;
+        return value.length >> coder();
     }
 
     /**
@@ -665,10 +682,11 @@
      *             string.
      */
     public char charAt(int index) {
-        if ((index < 0) || (index >= value.length)) {
-            throw new StringIndexOutOfBoundsException(index);
+        if (isLatin1()) {
+            return StringLatin1.charAt(value, index);
+        } else {
+            return StringUTF16.charAt(value, index);
         }
-        return value[index];
     }
 
     /**
@@ -694,10 +712,13 @@
      * @since      1.5
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= value.length)) {
-            throw new StringIndexOutOfBoundsException(index);
+        if (isLatin1()) {
+            checkIndex(index, value.length);
+            return value[index] & 0xff;
         }
-        return Character.codePointAtImpl(value, index, value.length);
+        int length = value.length >> 1;
+        checkIndex(index, length);
+        return StringUTF16.codePointAt(value, index, length);
     }
 
     /**
@@ -724,10 +745,13 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= value.length)) {
+        if (i < 0 || i >= length()) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBeforeImpl(value, index, 0);
+        if (isLatin1()) {
+            return (value[i] & 0xff);
+        }
+        return StringUTF16.codePointBefore(value, index);
     }
 
     /**
@@ -752,10 +776,14 @@
      * @since  1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
-        if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
+        if (beginIndex < 0 || beginIndex > endIndex ||
+            endIndex > length()) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
+        if (isLatin1()) {
+            return endIndex - beginIndex;
+        }
+        return StringUTF16.codePointCount(value, beginIndex, endIndex);
     }
 
     /**
@@ -779,19 +807,10 @@
      * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
-        if (index < 0 || index > value.length) {
+        if (index < 0 || index > length()) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.offsetByCodePointsImpl(value, 0, value.length,
-                index, codePointOffset);
-    }
-
-    /**
-     * Copy characters from this string into dst starting at dstBegin.
-     * This method doesn't perform any range checking.
-     */
-    void getChars(char dst[], int dstBegin) {
-        System.arraycopy(value, 0, dst, dstBegin, value.length);
+        return Character.offsetByCodePoints(this, index, codePointOffset);
     }
 
     /**
@@ -825,16 +844,13 @@
      *                {@code dst.length}</ul>
      */
     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(srcBegin);
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
         }
-        if (srcEnd > value.length) {
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        }
-        if (srcBegin > srcEnd) {
-            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
-        }
-        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
     }
 
     /**
@@ -882,24 +898,13 @@
      */
     @Deprecated
     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(srcBegin);
-        }
-        if (srcEnd > value.length) {
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        }
-        if (srcBegin > srcEnd) {
-            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
-        }
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
         Objects.requireNonNull(dst);
-
-        int j = dstBegin;
-        int n = srcEnd;
-        int i = srcBegin;
-        char[] val = value;   /* avoid getfield opcode */
-
-        while (i < n) {
-            dst[j++] = (byte)val[i++];
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
         }
     }
 
@@ -926,7 +931,7 @@
     public byte[] getBytes(String charsetName)
             throws UnsupportedEncodingException {
         if (charsetName == null) throw new NullPointerException();
-        return StringCoding.encode(charsetName, value, 0, value.length);
+        return StringCoding.encode(charsetName, coder(), value);
     }
 
     /**
@@ -949,8 +954,8 @@
      */
     public byte[] getBytes(Charset charset) {
         if (charset == null) throw new NullPointerException();
-        return StringCoding.encode(charset, value, 0, value.length);
-    }
+        return StringCoding.encode(charset, coder(), value);
+     }
 
     /**
      * Encodes this {@code String} into a sequence of bytes using the
@@ -966,7 +971,7 @@
      * @since      1.1
      */
     public byte[] getBytes() {
-        return StringCoding.encode(value, 0, value.length);
+        return StringCoding.encode(coder(), value);
     }
 
     /**
@@ -987,23 +992,15 @@
      * @see  #compareTo(String)
      * @see  #equalsIgnoreCase(String)
      */
-    @HotSpotIntrinsicCandidate
     public boolean equals(Object anObject) {
         if (this == anObject) {
             return true;
         }
         if (anObject instanceof String) {
-            char[] v1 = value;
-            char[] v2 = ((String)anObject).value;
-            int n = v1.length;
-            if (n == v2.length) {
-                int i = 0;
-                while (n-- != 0) {
-                    if (v1[i] != v2[i])
-                        return false;
-                    i++;
-                }
-                return true;
+            String aString = (String)anObject;
+            if (coder() == aString.coder()) {
+                return isLatin1() ? StringLatin1.equals(value, aString.value)
+                                  : StringUTF16.equals(value, aString.value);
             }
         }
         return false;
@@ -1032,16 +1029,28 @@
     }
 
     private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
-        char[] v1 = value;
-        char[] v2 = sb.getValue();
-        int n = v1.length;
-        if (n != sb.length()) {
+        int len = length();
+        if (len != sb.length()) {
             return false;
         }
-        for (int i = 0; i < n; i++) {
-            if (v1[i] != v2[i]) {
+        byte v1[] = value;
+        byte v2[] = sb.getValue();
+        if (coder() == sb.getCoder()) {
+            int n = v1.length;
+            for (int i = 0; i < n; i++) {
+                if (v1[i] != v2[i]) {
+                    return false;
+                }
+            }
+        } else {
+            if (!isLatin1()) {  // utf16 str and latin1 abs can never be "equal"
                 return false;
             }
+            for (int i = 0; i < len; i++) {
+                if ((char)(v1[i] & 0xff) != StringUTF16.getChar(v2, i)) {
+                    return false;
+                }
+            }
         }
         return true;
     }
@@ -1081,14 +1090,22 @@
             return equals(cs);
         }
         // Argument is a generic CharSequence
-        char[] v1 = value;
-        int n = v1.length;
-        if (n != cs.length()) {
+        int n = cs.length();
+        if (n != length()) {
             return false;
         }
-        for (int i = 0; i < n; i++) {
-            if (v1[i] != cs.charAt(i)) {
-                return false;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            for (int i = 0; i < n; i++) {
+                if ((val[i] & 0xff) != cs.charAt(i)) {
+                    return false;
+                }
+            }
+        } else {
+            for (int i = 0; i < n; i++) {
+                if (StringUTF16.getChar(val, i) != cs.charAt(i)) {
+                    return false;
+                }
             }
         }
         return true;
@@ -1125,8 +1142,8 @@
     public boolean equalsIgnoreCase(String anotherString) {
         return (this == anotherString) ? true
                 : (anotherString != null)
-                && (anotherString.value.length == value.length)
-                && regionMatches(true, 0, anotherString, 0, value.length);
+                && (anotherString.length() == length())
+                && regionMatches(true, 0, anotherString, 0, length());
     }
 
     /**
@@ -1173,23 +1190,16 @@
      *          value greater than {@code 0} if this string is
      *          lexicographically greater than the string argument.
      */
-    @HotSpotIntrinsicCandidate
     public int compareTo(String anotherString) {
-        char[] v1 = value;
-        char[] v2 = anotherString.value;
-        int len1 = v1.length;
-        int len2 = v2.length;
-        int lim = Math.min(len1, len2);
-
-        for (int k = 0; k < lim; k++) {
-            char c1 = v1[k];
-            char c2 = v2[k];
-            if (c1 != c2) {
-                return c1 - c2;
-            }
+        byte v1[] = value;
+        byte v2[] = anotherString.value;
+        if (coder() == anotherString.coder()) {
+            return isLatin1() ? StringLatin1.compareTo(v1, v2)
+                              : StringUTF16.compareTo(v1, v2);
         }
-        return len1 - len2;
-    }
+        return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
+                          : StringUTF16.compareToLatin1(v1, v2);
+     }
 
     /**
      * A Comparator that orders {@code String} objects as by
@@ -1210,12 +1220,18 @@
         private static final long serialVersionUID = 8575799808933029326L;
 
         public int compare(String s1, String s2) {
+            byte v1[] = s1.value;
+            byte v2[] = s2.value;
             int n1 = s1.length();
             int n2 = s2.length();
+            boolean s1IsLatin1 = s1.isLatin1();
+            boolean s2IsLatin1 = s2.isLatin1();
             int min = Math.min(n1, n2);
             for (int i = 0; i < min; i++) {
-                char c1 = s1.charAt(i);
-                char c2 = s2.charAt(i);
+                char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i)
+                                     : StringUTF16.getChar(v1, i);
+                char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i)
+                                     : StringUTF16.getChar(v2, i);
                 if (c1 != c2) {
                     c1 = Character.toUpperCase(c1);
                     c2 = Character.toUpperCase(c2);
@@ -1294,21 +1310,41 @@
      *          exactly matches the specified subregion of the string argument;
      *          {@code false} otherwise.
      */
-    public boolean regionMatches(int toffset, String other, int ooffset,
-            int len) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = other.value;
-        int po = ooffset;
+    public boolean regionMatches(int toffset, String other, int ooffset, int len) {
+        byte tv[] = value;
+        byte ov[] = other.value;
         // Note: toffset, ooffset, or len might be near -1>>>1.
-        if ((ooffset < 0) || (toffset < 0)
-                || (toffset > (long)ta.length - len)
-                || (ooffset > (long)pa.length - len)) {
+        if ((ooffset < 0) || (toffset < 0) ||
+             (toffset > (long)length() - len) ||
+             (ooffset > (long)other.length() - len)) {
             return false;
         }
-        while (len-- > 0) {
-            if (ta[to++] != pa[po++]) {
-                return false;
+        if (coder() == other.coder()) {
+            if (!isLatin1() && (len > 0)) {
+                toffset = toffset << 1;
+                ooffset = ooffset << 1;
+                len = len << 1;
+            }
+            while (len-- > 0) {
+                if (tv[toffset++] != ov[ooffset++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (coder() == LATIN1) {
+                while (len-- > 0) {
+                    if (StringLatin1.getChar(tv, toffset++) !=
+                        StringUTF16.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
+            } else {
+                while (len-- > 0) {
+                    if (StringUTF16.getChar(tv, toffset++) !=
+                        StringLatin1.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
             }
         }
         return true;
@@ -1366,43 +1402,25 @@
      */
     public boolean regionMatches(boolean ignoreCase, int toffset,
             String other, int ooffset, int len) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = other.value;
-        int po = ooffset;
+        if (!ignoreCase) {
+            return regionMatches(toffset, other, ooffset, len);
+        }
         // Note: toffset, ooffset, or len might be near -1>>>1.
         if ((ooffset < 0) || (toffset < 0)
-                || (toffset > (long)ta.length - len)
-                || (ooffset > (long)pa.length - len)) {
+                || (toffset > (long)length() - len)
+                || (ooffset > (long)other.length() - len)) {
             return false;
         }
-        while (len-- > 0) {
-            char c1 = ta[to++];
-            char c2 = pa[po++];
-            if (c1 == c2) {
-                continue;
-            }
-            if (ignoreCase) {
-                // If characters don't match but case may be ignored,
-                // try converting both characters to uppercase.
-                // If the results match, then the comparison scan should
-                // continue.
-                char u1 = Character.toUpperCase(c1);
-                char u2 = Character.toUpperCase(c2);
-                if (u1 == u2) {
-                    continue;
-                }
-                // Unfortunately, conversion to uppercase does not work properly
-                // for the Georgian alphabet, which has strange rules about case
-                // conversion.  So we need to make one last check before
-                // exiting.
-                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
-                    continue;
-                }
-            }
-            return false;
+        byte tv[] = value;
+        byte ov[] = other.value;
+        if (coder() == other.coder()) {
+            return isLatin1()
+              ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
         }
-        return true;
+        return isLatin1()
+              ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
     }
 
     /**
@@ -1423,19 +1441,31 @@
      *          </pre>
      */
     public boolean startsWith(String prefix, int toffset) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = prefix.value;
+        // Note: toffset might be near -1>>>1.
+        if (toffset < 0 || toffset > length() - prefix.length()) {
+            return false;
+        }
+        byte ta[] = value;
+        byte pa[] = prefix.value;
         int po = 0;
         int pc = pa.length;
-        // Note: toffset might be near -1>>>1.
-        if ((toffset < 0) || (toffset > ta.length - pc)) {
-            return false;
-        }
-        while (--pc >= 0) {
-            if (ta[to++] != pa[po++]) {
+        if (coder() == prefix.coder()) {
+            int to = isLatin1() ? toffset : toffset << 1;
+            while (po < pc) {
+                if (ta[to++] != pa[po++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (isLatin1()) {  // && pcoder == UTF16
                 return false;
             }
+            // coder == UTF16 && pcoder == LATIN1)
+            while (po < pc) {
+                if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) {
+                    return false;
+               }
+            }
         }
         return true;
     }
@@ -1469,7 +1499,7 @@
      *          as determined by the {@link #equals(Object)} method.
      */
     public boolean endsWith(String suffix) {
-        return startsWith(suffix, value.length - suffix.value.length);
+        return startsWith(suffix, length() - suffix.length());
     }
 
     /**
@@ -1486,16 +1516,11 @@
      * @return  a hash code value for this object.
      */
     public int hashCode() {
-        int h = hash;
-        if (h == 0) {
-            for (char v : value) {
-                h = 31 * h + v;
-            }
-            if (h != 0) {
-                hash = h;
-            }
+        if (hash == 0 && value.length > 0) {
+            hash = isLatin1() ? StringLatin1.hashCode(value)
+                              : StringUTF16.hashCode(value);
         }
-        return h;
+        return hash;
     }
 
     /**
@@ -1566,45 +1591,8 @@
      *          if the character does not occur.
      */
     public int indexOf(int ch, int fromIndex) {
-        final int max = value.length;
-        if (fromIndex < 0) {
-            fromIndex = 0;
-        } else if (fromIndex >= max) {
-            // Note: fromIndex might be near -1>>>1.
-            return -1;
-        }
-
-        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            // handle most cases here (ch is a BMP code point or a
-            // negative value (invalid code point))
-            final char[] value = this.value;
-            for (int i = fromIndex; i < max; i++) {
-                if (value[i] == ch) {
-                    return i;
-                }
-            }
-            return -1;
-        } else {
-            return indexOfSupplementary(ch, fromIndex);
-        }
-    }
-
-    /**
-     * Handles (rare) calls of indexOf with a supplementary character.
-     */
-    private int indexOfSupplementary(int ch, int fromIndex) {
-        if (Character.isValidCodePoint(ch)) {
-            final char[] value = this.value;
-            final char hi = Character.highSurrogate(ch);
-            final char lo = Character.lowSurrogate(ch);
-            final int max = value.length - 1;
-            for (int i = fromIndex; i < max; i++) {
-                if (value[i] == hi && value[i + 1] == lo) {
-                    return i;
-                }
-            }
-        }
-        return -1;
+        return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex)
+                          : StringUTF16.indexOf(value, ch, fromIndex);
     }
 
     /**
@@ -1631,7 +1619,7 @@
      *          {@code -1} if the character does not occur.
      */
     public int lastIndexOf(int ch) {
-        return lastIndexOf(ch, value.length - 1);
+        return lastIndexOf(ch, length() - 1);
     }
 
     /**
@@ -1669,38 +1657,8 @@
      *          if the character does not occur before that point.
      */
     public int lastIndexOf(int ch, int fromIndex) {
-        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            // handle most cases here (ch is a BMP code point or a
-            // negative value (invalid code point))
-            final char[] value = this.value;
-            int i = Math.min(fromIndex, value.length - 1);
-            for (; i >= 0; i--) {
-                if (value[i] == ch) {
-                    return i;
-                }
-            }
-            return -1;
-        } else {
-            return lastIndexOfSupplementary(ch, fromIndex);
-        }
-    }
-
-    /**
-     * Handles (rare) calls of lastIndexOf with a supplementary character.
-     */
-    private int lastIndexOfSupplementary(int ch, int fromIndex) {
-        if (Character.isValidCodePoint(ch)) {
-            final char[] value = this.value;
-            char hi = Character.highSurrogate(ch);
-            char lo = Character.lowSurrogate(ch);
-            int i = Math.min(fromIndex, value.length - 2);
-            for (; i >= 0; i--) {
-                if (value[i] == hi && value[i + 1] == lo) {
-                    return i;
-                }
-            }
-        }
-        return -1;
+        return isLatin1() ? StringLatin1.lastIndexOf(value, ch, fromIndex)
+                          : StringUTF16.lastIndexOf(value, ch, fromIndex);
     }
 
     /**
@@ -1717,9 +1675,15 @@
      * @return  the index of the first occurrence of the specified substring,
      *          or {@code -1} if there is no such occurrence.
      */
-    @HotSpotIntrinsicCandidate
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        if (coder() == str.coder()) {
+            return isLatin1() ? StringLatin1.indexOf(value, str.value)
+                              : StringUTF16.indexOf(value, str.value);
+        }
+        if (coder() == LATIN1) {  // str.coder == UTF16
+            return -1;
+        }
+        return StringUTF16.indexOfLatin1(value, str.value);
     }
 
     /**
@@ -1740,8 +1704,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        return indexOf(value, 0, value.length,
-                str.value, 0, str.value.length, fromIndex);
+        return indexOf(value, coder(), length(), str, fromIndex);
     }
 
     /**
@@ -1749,68 +1712,38 @@
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   fromIndex    the index to begin searching from.
+     * @param   src       the characters being searched.
+     * @param   srcCoder  the coder of the source string.
+     * @param   srcCount  length of the source string.
+     * @param   tgtStr    the characters being searched for.
+     * @param   fromIndex the index to begin searching from.
      */
-    static int indexOf(char[] source, int sourceOffset, int sourceCount,
-            String target, int fromIndex) {
-        return indexOf(source, sourceOffset, sourceCount,
-                       target.value, 0, target.value.length,
-                       fromIndex);
-    }
+    static int indexOf(byte[] src, byte srcCoder, int srcCount,
+                       String tgtStr, int fromIndex) {
 
-    /**
-     * Code shared by String and StringBuffer to do searches. The
-     * source is the character array being searched, and the target
-     * is the string being searched for.
-     *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
-     * @param   fromIndex    the index to begin searching from.
-     */
-    static int indexOf(char[] source, int sourceOffset, int sourceCount,
-            char[] target, int targetOffset, int targetCount,
-            int fromIndex) {
-        if (fromIndex >= sourceCount) {
-            return (targetCount == 0 ? sourceCount : -1);
+        byte[] tgt    = tgtStr.value;
+        byte tgtCoder = tgtStr.coder();
+        int tgtCount  = tgtStr.length();
+
+        if (fromIndex >= srcCount) {
+            return (tgtCount == 0 ? srcCount : -1);
         }
         if (fromIndex < 0) {
             fromIndex = 0;
         }
-        if (targetCount == 0) {
+        if (tgtCount == 0) {
             return fromIndex;
         }
-
-        char first = target[targetOffset];
-        int max = sourceOffset + (sourceCount - targetCount);
-
-        for (int i = sourceOffset + fromIndex; i <= max; i++) {
-            /* Look for first character. */
-            if (source[i] != first) {
-                while (++i <= max && source[i] != first);
-            }
-
-            /* Found first character, now look at the rest of v2 */
-            if (i <= max) {
-                int j = i + 1;
-                int end = j + targetCount - 1;
-                for (int k = targetOffset + 1; j < end && source[j]
-                        == target[k]; j++, k++);
-
-                if (j == end) {
-                    /* Found whole string. */
-                    return i - sourceOffset;
-                }
-            }
+        if (srcCoder == tgtCoder) {
+            return srcCoder == LATIN1
+                ? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex)
+                : StringUTF16.indexOf(src, srcCount, tgt, tgtCount, fromIndex);
         }
-        return -1;
+        if (srcCoder == LATIN1) {    //  && tgtCoder == UTF16
+            return -1;
+        }
+        // srcCoder == UTF16 && tgtCoder == LATIN1) {
+        return StringUTF16.indexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
     }
 
     /**
@@ -1829,7 +1762,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str) {
-        return lastIndexOf(str, value.length);
+        return lastIndexOf(str, length());
     }
 
     /**
@@ -1850,8 +1783,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        return lastIndexOf(value, 0, value.length,
-                str.value, 0, str.value.length, fromIndex);
+        return lastIndexOf(value, coder(), length(), str, fromIndex);
     }
 
     /**
@@ -1859,40 +1791,22 @@
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   fromIndex    the index to begin searching from.
+     * @param   src         the characters being searched.
+     * @param   srcCoder  coder handles the mapping between bytes/chars
+     * @param   srcCount    count of the source string.
+     * @param   tgt         the characters being searched for.
+     * @param   fromIndex   the index to begin searching from.
      */
-    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
-            String target, int fromIndex) {
-        return lastIndexOf(source, sourceOffset, sourceCount,
-                       target.value, 0, target.value.length,
-                       fromIndex);
-    }
-
-    /**
-     * Code shared by String and StringBuffer to do searches. The
-     * source is the character array being searched, and the target
-     * is the string being searched for.
-     *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
-     * @param   fromIndex    the index to begin searching from.
-     */
-    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
-            char[] target, int targetOffset, int targetCount,
-            int fromIndex) {
+    static int lastIndexOf(byte[] src, byte srcCoder, int srcCount,
+                           String tgtStr, int fromIndex) {
+        byte[] tgt = tgtStr.value;
+        byte tgtCoder = tgtStr.coder();
+        int tgtCount = tgtStr.length();
         /*
          * Check arguments; return immediately where possible. For
          * consistency, don't check for null str.
          */
-        int rightIndex = sourceCount - targetCount;
+        int rightIndex = srcCount - tgtCount;
         if (fromIndex < 0) {
             return -1;
         }
@@ -1900,34 +1814,41 @@
             fromIndex = rightIndex;
         }
         /* Empty string always matches. */
-        if (targetCount == 0) {
+        if (tgtCount == 0) {
             return fromIndex;
         }
+        if (srcCoder == tgtCoder) {
+            return srcCoder == LATIN1
+                ? StringLatin1.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex)
+                : StringUTF16.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex);
+        }
+        if (srcCoder == LATIN1) {    // && tgtCoder == UTF16
+            return -1;
+        }
+                                     // srcCoder == UTF16 && tgtCoder == LATIN1
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
 
-        int strLastIndex = targetOffset + targetCount - 1;
-        char strLastChar = target[strLastIndex];
-        int min = sourceOffset + targetCount - 1;
-        int i = min + fromIndex;
-
+        char strLastChar = (char)(tgt[strLastIndex] & 0xff);
     startSearchForLastChar:
         while (true) {
-            while (i >= min && source[i] != strLastChar) {
+            while (i >= min && StringUTF16.getChar(src, i) != strLastChar) {
                 i--;
             }
             if (i < min) {
                 return -1;
             }
             int j = i - 1;
-            int start = j - (targetCount - 1);
+            int start = j - strLastIndex;
             int k = strLastIndex - 1;
-
             while (j > start) {
-                if (source[j--] != target[k--]) {
+                if (StringUTF16.getChar(src, j--) != (tgt[k--] & 0xff)) {
                     i--;
                     continue startSearchForLastChar;
                 }
             }
-            return start - sourceOffset + 1;
+            return start + 1;
         }
     }
 
@@ -1949,17 +1870,18 @@
      *             length of this {@code String} object.
      */
     public String substring(int beginIndex) {
-        if (beginIndex <= 0) {
-            if (beginIndex < 0) {
-                throw new StringIndexOutOfBoundsException(beginIndex);
-            }
-            return this;
+        if (beginIndex < 0) {
+            throw new StringIndexOutOfBoundsException(beginIndex);
         }
-        int subLen = value.length - beginIndex;
+        int subLen = length() - beginIndex;
         if (subLen < 0) {
             throw new StringIndexOutOfBoundsException(subLen);
         }
-        return new String(value, beginIndex, subLen);
+        if (beginIndex == 0) {
+            return this;
+        }
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
     }
 
     /**
@@ -1985,22 +1907,14 @@
      *             {@code endIndex}.
      */
     public String substring(int beginIndex, int endIndex) {
-        if (beginIndex <= 0) {
-            if (beginIndex < 0) {
-                throw new StringIndexOutOfBoundsException(beginIndex);
-            }
-            if (endIndex == value.length) {
-                return this;
-            }
+        int length = length();
+        checkBoundsBeginEnd(beginIndex, endIndex, length);
+        int subLen = endIndex - beginIndex;
+        if (beginIndex == 0 && endIndex == length) {
+            return this;
         }
-        if (endIndex > value.length) {
-            throw new StringIndexOutOfBoundsException(endIndex);
-        }
-        int subLen = endIndex - beginIndex;
-        if (subLen < 0) {
-            throw new StringIndexOutOfBoundsException(subLen);
-        }
-        return new String(value, beginIndex, subLen);
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
     }
 
     /**
@@ -2057,14 +1971,23 @@
      *          characters followed by the string argument's characters.
      */
     public String concat(String str) {
-        int otherLen = str.length();
-        if (otherLen == 0) {
+        int olen = str.length();
+        if (olen == 0) {
             return this;
         }
-        int len = value.length;
-        char[] buf = Arrays.copyOf(value, len + otherLen);
-        str.getChars(buf, len);
-        return new String(buf, true);
+        if (coder() == str.coder()) {
+            byte[] val = this.value;
+            byte[] oval = str.value;
+            int len = val.length + oval.length;
+            byte[] buf = Arrays.copyOf(val, len);
+            System.arraycopy(oval, 0, buf, val.length, oval.length);
+            return new String(buf, coder);
+        }
+        int len = length();
+        byte[] buf = StringUTF16.newBytesFor(len + olen);
+        getBytes(buf, 0, UTF16);
+        str.getBytes(buf, len, UTF16);
+        return new String(buf, UTF16);
     }
 
     /**
@@ -2098,26 +2021,10 @@
      */
     public String replace(char oldChar, char newChar) {
         if (oldChar != newChar) {
-            char[] val = value; /* avoid getfield opcode */
-            int len = val.length;
-            int i = -1;
-
-            while (++i < len) {
-                if (val[i] == oldChar) {
-                    break;
-                }
-            }
-            if (i < len) {
-                char[] buf = new char[len];
-                for (int j = 0; j < i; j++) {
-                    buf[j] = val[j];
-                }
-                while (i < len) {
-                    char c = val[i];
-                    buf[i] = (c == oldChar) ? newChar : c;
-                    i++;
-                }
-                return new String(buf, true);
+            String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar)
+                                    : StringUTF16.replace(value, oldChar, newChar);
+            if (ret != null) {
+                return ret;
             }
         }
         return this;
@@ -2269,29 +2176,27 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        String starget = target.toString();
-        String srepl = replacement.toString();
-        int j = indexOf(starget);
+        String tgtStr = target.toString();
+        String replStr = replacement.toString();
+        int j = indexOf(tgtStr);
         if (j < 0) {
             return this;
         }
-        int targLen = starget.length();
-        int targLen1 = Math.max(targLen, 1);
-        final char[] value = this.value;
-        final char[] replValue = srepl.value;
-        int newLenHint = value.length - targLen + replValue.length;
+        int tgtLen = tgtStr.length();
+        int tgtLen1 = Math.max(tgtLen, 1);
+        int thisLen = length();
+
+        int newLenHint = thisLen - tgtLen + replStr.length();
         if (newLenHint < 0) {
             throw new OutOfMemoryError();
         }
         StringBuilder sb = new StringBuilder(newLenHint);
         int i = 0;
         do {
-            sb.append(value, i, j - i)
-                    .append(replValue);
-            i = j + targLen;
-        } while (j < value.length && (j = indexOf(starget, j + targLen1)) > 0);
-
-        return sb.append(value, i, value.length - i).toString();
+            sb.append(this, i, j).append(replStr);
+            i = j + tgtLen;
+        } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
+        return sb.append(this, i, thisLen).toString();
     }
 
     /**
@@ -2388,7 +2293,7 @@
             the second is not the ascii digit or ascii letter.
          */
         char ch = 0;
-        if (((regex.value.length == 1 &&
+        if (((regex.length() == 1 &&
              ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
              (regex.length() == 2 &&
               regex.charAt(0) == '\\' &&
@@ -2408,8 +2313,9 @@
                     off = next + 1;
                 } else {    // last one
                     //assert (list.size() == limit - 1);
-                    list.add(substring(off, value.length));
-                    off = value.length;
+                    int last = length();
+                    list.add(substring(off, last));
+                    off = last;
                     break;
                 }
             }
@@ -2419,7 +2325,7 @@
 
             // Add remaining segment
             if (!limited || list.size() < limit)
-                list.add(substring(off, value.length));
+                list.add(substring(off, length()));
 
             // Construct result
             int resultSize = list.size();
@@ -2613,95 +2519,8 @@
      * @since   1.1
      */
     public String toLowerCase(Locale locale) {
-        if (locale == null) {
-            throw new NullPointerException();
-        }
-        int first;
-        boolean hasSurr = false;
-        final int len = value.length;
-
-        // Now check if there are any characters that need to be changed, or are surrogate
-        for (first = 0 ; first < len; first++) {
-            int cp = (int)value[first];
-            if (Character.isSurrogate((char)cp)) {
-                hasSurr = true;
-                break;
-            }
-            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
-                break;
-            }
-        }
-        if (first == len)
-            return this;
-        char[] result = new char[len];
-        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
-                                                       // lowerCase characters.
-        String lang = locale.getLanguage();
-        if (lang == "tr" || lang == "az" || lang == "lt") {
-            return toLowerCaseEx(result, first, locale, true);
-        }
-        if (hasSurr) {
-            return toLowerCaseEx(result, first, locale, false);
-        }
-        for (int i = first; i < len; i++) {
-            int cp = (int)value[i];
-            if (cp == '\u03A3' ||                       // GREEK CAPITAL LETTER SIGMA
-                Character.isSurrogate((char)cp)) {
-                return toLowerCaseEx(result, i, locale, false);
-            }
-            if (cp == '\u0130') {                       // LATIN CAPITAL LETTER I WITH DOT ABOVE
-                return toLowerCaseEx(result, i, locale, true);
-            }
-            cp = Character.toLowerCase(cp);
-            if (!Character.isBmpCodePoint(cp)) {
-                return toLowerCaseEx(result, i, locale, false);
-            }
-            result[i] = (char)cp;
-        }
-        return new String(result, true);
-    }
-
-    private String toLowerCaseEx(char[] result, int first, Locale locale, boolean localeDependent) {
-        int resultOffset = first;
-        int srcCount;
-        for (int i = first; i < value.length; i += srcCount) {
-            int srcChar = (int)value[i];
-            int lowerChar;
-            char[] lowerCharArray;
-            srcCount = 1;
-            if (Character.isSurrogate((char)srcChar)) {
-                srcChar = codePointAt(i);
-                srcCount = Character.charCount(srcChar);
-            }
-            if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
-                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
-            } else {
-                lowerChar = Character.toLowerCase(srcChar);
-            }
-            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
-                result[resultOffset++] = (char)lowerChar;
-            } else {
-                if (lowerChar == Character.ERROR) {
-                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
-                } else if (srcCount == 2) {
-                    resultOffset += Character.toChars(lowerChar, result, resultOffset);
-                    continue;
-                } else {
-                    lowerCharArray = Character.toChars(lowerChar);
-                }
-                /* Grow result if needed */
-                int mapLen = lowerCharArray.length;
-                if (mapLen > srcCount) {
-                    char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0, resultOffset);
-                    result = result2;
-                }
-                for (int x = 0; x < mapLen; ++x) {
-                    result[resultOffset++] = lowerCharArray[x];
-                }
-            }
-        }
-        return new String(result, 0, resultOffset);
+        return isLatin1() ? StringLatin1.toLowerCase(this, value, locale)
+                          : StringUTF16.toLowerCase(this, value, locale);
     }
 
     /**
@@ -2776,98 +2595,8 @@
      * @since   1.1
      */
     public String toUpperCase(Locale locale) {
-        if (locale == null) {
-            throw new NullPointerException();
-        }
-        int first;
-        boolean hasSurr = false;
-        final int len = value.length;
-
-        // Now check if there are any characters that need to be changed, or are surrogate
-        for (first = 0 ; first < len; first++ ) {
-            int cp = (int)value[first];
-            if (Character.isSurrogate((char)cp)) {
-                hasSurr = true;
-                break;
-            }
-            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
-                break;
-            }
-        }
-        if (first == len) {
-            return this;
-        }
-        char[] result = new char[len];
-        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
-                                                       // upperCase characters.
-        String lang = locale.getLanguage();
-        if (lang == "tr" || lang == "az" || lang == "lt") {
-            return toUpperCaseEx(result, first, locale, true);
-        }
-        if (hasSurr) {
-            return toUpperCaseEx(result, first, locale, false);
-        }
-        for (int i = first; i < len; i++) {
-            int cp = (int)value[i];
-            if (Character.isSurrogate((char)cp)) {
-                return toUpperCaseEx(result, i, locale, false);
-            }
-            cp = Character.toUpperCaseEx(cp);
-            if (!Character.isBmpCodePoint(cp)) {    // Character.ERROR is not bmp
-                return toUpperCaseEx(result, i, locale, false);
-            }
-            result[i] = (char)cp;
-        }
-        return new String(result, true);
-    }
-
-    private String toUpperCaseEx(char[] result, int first, Locale locale,
-                                 boolean localeDependent) {
-        int resultOffset = first;
-        int srcCount;
-        for (int i = first; i < value.length; i += srcCount) {
-            int srcChar = (int)value[i];
-            int upperChar;
-            char[] upperCharArray;
-            srcCount = 1;
-            if (Character.isSurrogate((char)srcChar)) {
-                srcChar = codePointAt(i);
-                srcCount = Character.charCount(srcChar);
-            }
-            if (localeDependent) {
-                upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
-            } else {
-                upperChar = Character.toUpperCaseEx(srcChar);
-            }
-            if (Character.isBmpCodePoint(upperChar)) {
-                result[resultOffset++] = (char)upperChar;
-            } else {
-                if (upperChar == Character.ERROR) {
-                    if (localeDependent) {
-                        upperCharArray =
-                            ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
-                    } else {
-                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
-                    }
-                } else if (srcCount == 2) {
-                    resultOffset += Character.toChars(upperChar, result, resultOffset);
-                    continue;
-                } else {
-                    upperCharArray = Character.toChars(upperChar);
-                }
-                /* Grow result if needed */
-                int mapLen = upperCharArray.length;
-                if (mapLen > srcCount) {
-                    char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0, resultOffset);
-                    result = result2;
-                 }
-                 for (int x = 0; x < mapLen; ++x) {
-                    result[resultOffset++] = upperCharArray[x];
-                 }
-            }
-        }
-        return new String(result, 0, resultOffset);
+        return isLatin1() ? StringLatin1.toUpperCase(this, value, locale)
+                          : StringUTF16.toUpperCase(this, value, locale);
     }
 
     /**
@@ -2925,17 +2654,9 @@
      *          trailing white space.
      */
     public String trim() {
-        char[] val = value;    /* avoid getfield opcode */
-        int end = val.length;
-        int beg = 0;
-
-        while ((beg < end) && (val[beg] <= ' ')) {
-            beg++;
-        }
-        while ((beg < end) && (val[end - 1] <= ' ')) {
-            end--;
-        }
-        return substring(beg, end);
+        String ret = isLatin1() ? StringLatin1.trim(value)
+                                : StringUTF16.trim(value);
+        return ret == null ? this : ret;
     }
 
     /**
@@ -2947,63 +2668,6 @@
         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
@@ -3016,93 +2680,11 @@
     @Override
     public IntStream chars() {
         return StreamSupport.intStream(
-                new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CharsSpliterator(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
@@ -3118,7 +2700,9 @@
     @Override
     public IntStream codePoints() {
         return StreamSupport.intStream(
-                new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CodePointsSpliterator(value, Spliterator.IMMUTABLE),
+            false);
     }
 
     /**
@@ -3129,10 +2713,8 @@
      *          the character sequence represented by this string.
      */
     public char[] toCharArray() {
-        // Cannot use Arrays.copyOf because of class initialization order issues
-        char[] result = new char[value.length];
-        System.arraycopy(value, 0, result, 0, value.length);
-        return result;
+        return isLatin1() ? StringLatin1.toChars(value)
+                          : StringUTF16.toChars(value);
     }
 
     /**
@@ -3315,7 +2897,10 @@
      *          as its single character the argument {@code c}.
      */
     public static String valueOf(char c) {
-        return new String(new char[]{c}, true);
+        if (COMPACT_STRINGS && StringLatin1.canEncode(c)) {
+            return new String(StringLatin1.toBytes(c), LATIN1);
+        }
+        return new String(StringUTF16.toBytes(c), UTF16);
     }
 
     /**
@@ -3398,4 +2983,145 @@
      *          guaranteed to be from a pool of unique strings.
      */
     public native String intern();
+
+    ////////////////////////////////////////////////////////////////
+
+    /**
+     * Copy character bytes from this string into dst starting at dstBegin.
+     * This method doesn't perform any range checking.
+     *
+     * Invoker guarantees: dst is in UTF16 (inflate itself for asb), if two
+     * coders are different, and dst is big enough (range check)
+     *
+     * @param dstBegin  the char index, not offset of byte[]
+     * @param coder     the coder of dst[]
+     */
+    void getBytes(byte dst[], int dstBegin, byte coder) {
+        if (coder() == coder) {
+            System.arraycopy(value, 0, dst, dstBegin << coder, value.length);
+        } else {    // this.coder == LATIN && coder == UTF16
+            StringLatin1.inflate(value, 0, dst, dstBegin, value.length);
+        }
+    }
+
+    /*
+     * Package private constructor. Trailing Void argument is there for
+     * disambiguating it against other (public) constructors.
+     *
+     * Stores the char[] value into a byte[] that each byte represents
+     * the8 low-order bits of the corresponding character, if the char[]
+     * contains only latin1 character. Or a byte[] that stores all
+     * characters in their byte sequences defined by the {@code StringUTF16}.
+     */
+    String(char[] value, int off, int len, Void sig) {
+        if (len == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS) {
+            byte[] val = StringUTF16.compress(value, off, len);
+            if (val != null) {
+                this.value = val;
+                this.coder = LATIN1;
+                return;
+            }
+        }
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(value, off, len);
+    }
+
+    /*
+     * Package private constructor. Trailing Void argument is there for
+     * disambiguating it against other (public) constructors.
+     */
+    String(AbstractStringBuilder asb, Void sig) {
+        byte[] val = asb.getValue();
+        int length = asb.length();
+        if (asb.isLatin1()) {
+            this.coder = LATIN1;
+            this.value = Arrays.copyOfRange(val, 0, length);
+        } else {
+            if (COMPACT_STRINGS) {
+                byte[] buf = StringUTF16.compress(val, 0, length);
+                if (buf != null) {
+                    this.coder = LATIN1;
+                    this.value = buf;
+                    return;
+                }
+            }
+            this.coder = UTF16;
+            this.value = Arrays.copyOfRange(val, 0, length << 1);
+        }
+    }
+
+   /*
+    * Package private constructor which shares value array for speed.
+    */
+    String(byte[] value, byte coder) {
+        this.value = value;
+        this.coder = coder;
+    }
+
+    byte coder() {
+        return COMPACT_STRINGS ? coder : UTF16;
+    }
+
+    private boolean isLatin1() {
+        return COMPACT_STRINGS && coder == LATIN1;
+    }
+
+    static final byte LATIN1 = 0;
+    static final byte UTF16  = 1;
+
+    /*
+     * StringIndexOutOfBoundsException  if {@code index} is
+     * negative or greater than or equal to {@code length}.
+     */
+    static void checkIndex(int index, int length) {
+        if (index < 0 || index >= length) {
+            throw new StringIndexOutOfBoundsException("index " + index);
+        }
+    }
+
+    /*
+     * StringIndexOutOfBoundsException  if {@code offset}
+     * is negative or greater than {@code length}.
+     */
+    static void checkOffset(int offset, int length) {
+        if (offset < 0 || offset > length) {
+            throw new StringIndexOutOfBoundsException("offset " + offset +
+                                                      ",length " + length);
+        }
+    }
+
+    /*
+     * Check {@code offset}, {@code count} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code offset} is negative, {@code count} is negative,
+     *          or {@code offset} is greater than {@code length - count}
+     */
+    private static void checkBoundsOffCount(int offset, int count, int length) {
+        if (offset < 0 || count < 0 || offset > length - count) {
+            throw new StringIndexOutOfBoundsException(
+                "offset " + offset + ", count " + count + ", length " + length);
+        }
+    }
+
+    /*
+     * Check {@code begin}, {@code end} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code begin} is negative, {@code begin} is greater than
+     *          {@code end}, or {@code end} is greater than {@code length}.
+     */
+    private static void checkBoundsBeginEnd(int begin, int end, int length) {
+        if (begin < 0 || begin > end || end > length) {
+            throw new StringIndexOutOfBoundsException(
+                "begin " + begin + ", end " + end + ", length " + length);
+        }
+    }
 }
--- a/src/java.base/share/classes/java/lang/StringBuffer.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StringBuffer.java	Thu Nov 12 14:15:05 2015 -0800
@@ -104,7 +104,7 @@
      * A cache of the last value returned by toString. Cleared
      * whenever the StringBuffer is modified.
      */
-    private transient char[] toStringCache;
+    private transient String toStringCache;
 
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     static final long serialVersionUID = 3388685877147921107L;
@@ -169,15 +169,13 @@
 
     @Override
     public synchronized int capacity() {
-        return value.length;
+        return super.capacity();
     }
 
 
     @Override
     public synchronized void ensureCapacity(int minimumCapacity) {
-        if (minimumCapacity > value.length) {
-            expandCapacity(minimumCapacity);
-        }
+        super.ensureCapacity(minimumCapacity);
     }
 
     /**
@@ -204,9 +202,7 @@
      */
     @Override
     public synchronized char charAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        return value[index];
+        return super.charAt(index);
     }
 
     /**
@@ -261,10 +257,8 @@
      */
     @Override
     public synchronized void setCharAt(int index, char ch) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
         toStringCache = null;
-        value[index] = ch;
+        super.setCharAt(index, ch);
     }
 
     @Override
@@ -680,9 +674,11 @@
     @HotSpotIntrinsicCandidate
     public synchronized String toString() {
         if (toStringCache == null) {
-            toStringCache = Arrays.copyOfRange(value, 0, count);
+            return toStringCache =
+                    isLatin1() ? StringLatin1.newString(value, 0, count)
+                               : StringUTF16.newString(value, 0, count);
         }
-        return new String(toStringCache, true);
+        return new String(toStringCache);
     }
 
     /**
@@ -710,7 +706,13 @@
     private synchronized void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
         java.io.ObjectOutputStream.PutField fields = s.putFields();
-        fields.put("value", value);
+        char[] val = new char[capacity()];
+        if (isLatin1()) {
+            StringLatin1.getChars(value, 0, count, val, 0);
+        } else {
+            StringUTF16.getChars(value, 0, count, val, 0);
+        }
+        fields.put("value", val);
         fields.put("count", count);
         fields.put("shared", false);
         s.writeFields();
@@ -723,7 +725,12 @@
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         java.io.ObjectInputStream.GetField fields = s.readFields();
-        value = (char[])fields.get("value", null);
+        char[] val = (char[])fields.get("value", null);
+        initBytes(val, 0, val.length);
         count = fields.get("count", 0);
     }
+
+    protected synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
+        super.getBytes(dst, dstBegin, coder);
+    }
 }
--- a/src/java.base/share/classes/java/lang/StringBuilder.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StringBuilder.java	Thu Nov 12 14:15:05 2015 -0800
@@ -412,7 +412,8 @@
     @HotSpotIntrinsicCandidate
     public String toString() {
         // Create a copy, don't share the array
-        return new String(value, 0, count);
+        return isLatin1() ? StringLatin1.newString(value, 0, count)
+                          : StringUTF16.newStringSB(value, 0, count);
     }
 
     /**
@@ -430,7 +431,13 @@
         throws java.io.IOException {
         s.defaultWriteObject();
         s.writeInt(count);
-        s.writeObject(value);
+        char[] val = new char[capacity()];
+        if (isLatin1()) {
+            StringLatin1.getChars(value, 0, count, val, 0);
+        } else {
+            StringUTF16.getChars(value, 0, count, val, 0);
+        }
+        s.writeObject(val);
     }
 
     /**
@@ -441,7 +448,8 @@
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
         count = s.readInt();
-        value = (char[]) s.readObject();
+        char[] val = (char[]) s.readObject();
+        initBytes(val, 0, val.length);
     }
 
 }
--- a/src/java.base/share/classes/java/lang/StringCoding.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StringCoding.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, 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
@@ -38,11 +38,19 @@
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.Arrays;
+import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.misc.MessageUtils;
 import sun.nio.cs.HistoricallyNamedCharset;
 import sun.nio.cs.ArrayDecoder;
 import sun.nio.cs.ArrayEncoder;
 
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.COMPACT_STRINGS;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 /**
  * Utility class for string encoding and decoding.
  */
@@ -72,23 +80,13 @@
 
     // Trim the given byte array to the given length
     //
-    private static byte[] safeTrim(byte[] ba, int len, Charset cs, boolean isTrusted) {
+    private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) {
         if (len == ba.length && (isTrusted || System.getSecurityManager() == null))
             return ba;
         else
             return Arrays.copyOf(ba, len);
     }
 
-    // Trim the given char array to the given length
-    //
-    private static char[] safeTrim(char[] ca, int len,
-                                   Charset cs, boolean isTrusted) {
-        if (len == ca.length && (isTrusted || System.getSecurityManager() == null))
-            return ca;
-        else
-            return Arrays.copyOf(ca, len);
-    }
-
     private static int scale(int len, float expansionFactor) {
         // We need to perform double, not float, arithmetic; otherwise
         // we lose low order bits when len is larger than 2**24.
@@ -117,21 +115,64 @@
         }
     }
 
+    static class Result {
+        byte[] value;
+        byte coder;
+
+        Result with() {
+            coder = COMPACT_STRINGS ? LATIN1 : UTF16;
+            value = new byte[0];
+            return this;
+        }
+
+        Result with(char[] val, int off, int len) {
+            if (String.COMPACT_STRINGS) {
+                byte[] bs = StringUTF16.compress(val, off, len);
+                if (bs != null) {
+                    value = bs;
+                    coder = LATIN1;
+                    return this;
+                }
+            }
+            coder = UTF16;
+            value = StringUTF16.toBytes(val, off, len);
+            return this;
+        }
+
+        Result with(byte[] val, byte coder) {
+            this.coder = coder;
+            value = val;
+            return this;
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    private static boolean hasNegatives(byte[] ba, int off, int len) {
+        for (int i = off; i < off + len; i++) {
+            if (ba[i] < 0) {
+                return true;
+            }
+        }
+        return false;
+    }
 
     // -- Decoding --
-    private static class StringDecoder {
+    static class StringDecoder {
         private final String requestedCharsetName;
         private final Charset cs;
+        private final boolean isASCIICompatible;
         private final CharsetDecoder cd;
-        private final boolean isTrusted;
+        protected final Result result;
 
-        private StringDecoder(Charset cs, String rcn) {
+        StringDecoder(Charset cs, String rcn) {
             this.requestedCharsetName = rcn;
             this.cs = cs;
             this.cd = cs.newDecoder()
                 .onMalformedInput(CodingErrorAction.REPLACE)
                 .onUnmappableCharacter(CodingErrorAction.REPLACE);
-            this.isTrusted = (cs.getClass().getClassLoader0() == null);
+            this.result = new Result();
+            this.isASCIICompatible = (cd instanceof ArrayDecoder) &&
+                    ((ArrayDecoder)cd).isASCIICompatible();
         }
 
         String charsetName() {
@@ -144,36 +185,58 @@
             return requestedCharsetName;
         }
 
-        char[] decode(byte[] ba, int off, int len) {
+        Result decode(byte[] ba, int off, int len) {
+            if (len == 0) {
+                return result.with();
+            }
+            // fastpath for ascii compatible
+            if (isASCIICompatible && !hasNegatives(ba, off, len)) {
+                if (COMPACT_STRINGS) {
+                    return result.with(Arrays.copyOfRange(ba, off, off + len),
+                                      LATIN1);
+                } else {
+                    return result.with(StringLatin1.inflate(ba, off, len), UTF16);
+                }
+            }
             int en = scale(len, cd.maxCharsPerByte());
             char[] ca = new char[en];
-            if (len == 0)
-                return ca;
             if (cd instanceof ArrayDecoder) {
                 int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
-                return safeTrim(ca, clen, cs, isTrusted);
+                return result.with(ca, 0, clen);
+            }
+            cd.reset();
+            ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+            CharBuffer cb = CharBuffer.wrap(ca);
+            try {
+                CoderResult cr = cd.decode(bb, cb, true);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+                cr = cd.flush(cb);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+            } catch (CharacterCodingException x) {
+                // Substitution is always enabled,
+                // so this shouldn't happen
+                throw new Error(x);
+            }
+            return result.with(ca, 0, cb.position());
+        }
+    }
+
+    private static class StringDecoder8859_1 extends StringDecoder {
+        StringDecoder8859_1(Charset cs, String rcn) {
+            super(cs, rcn);
+        }
+        Result decode(byte[] ba, int off, int len) {
+            if (COMPACT_STRINGS) {
+                return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
             } else {
-                cd.reset();
-                ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
-                CharBuffer cb = CharBuffer.wrap(ca);
-                try {
-                    CoderResult cr = cd.decode(bb, cb, true);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                    cr = cd.flush(cb);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                } catch (CharacterCodingException x) {
-                    // Substitution is always enabled,
-                    // so this shouldn't happen
-                    throw new Error(x);
-                }
-                return safeTrim(ca, cb.position(), cs, isTrusted);
+                return result.with(StringLatin1.inflate(ba, off, len), UTF16);
             }
         }
     }
 
-    static char[] decode(String charsetName, byte[] ba, int off, int len)
+    static Result decode(String charsetName, byte[] ba, int off, int len)
         throws UnsupportedEncodingException
     {
         StringDecoder sd = deref(decoder);
@@ -183,8 +246,15 @@
             sd = null;
             try {
                 Charset cs = lookupCharset(csn);
-                if (cs != null)
-                    sd = new StringDecoder(cs, csn);
+                if (cs != null) {
+                    if (cs == UTF_8) {
+                        sd = new StringDecoderUTF8(cs, csn);
+                    } else if (cs == ISO_8859_1) {
+                        sd = new StringDecoder8859_1(cs, csn);
+                    } else {
+                        sd = new StringDecoder(cs, csn);
+                    }
+                }
             } catch (IllegalCharsetNameException x) {}
             if (sd == null)
                 throw new UnsupportedEncodingException(csn);
@@ -193,7 +263,7 @@
         return sd.decode(ba, off, len);
     }
 
-    static char[] decode(Charset cs, byte[] ba, int off, int len) {
+    static Result decode(Charset cs, byte[] ba, int off, int len) {
         // (1)We never cache the "external" cs, the only benefit of creating
         // an additional StringDe/Encoder object to wrap it is to share the
         // de/encode() method. These SD/E objects are short-lived, the young-gen
@@ -210,44 +280,57 @@
         // check (... && (isTrusted || SM == null || getClassLoader0())) in trim
         // but it then can be argued that the SM is null when the operation
         // is started...
+        if (cs == UTF_8) {
+            return StringDecoderUTF8.decode(ba, off, len, new Result());
+        }
         CharsetDecoder cd = cs.newDecoder();
+        // ascii fastpath
+        if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) &&
+                                 ((ArrayDecoder)cd).isASCIICompatible() &&
+                                 !hasNegatives(ba, off, len))) {
+             if (COMPACT_STRINGS) {
+                 return new Result().with(Arrays.copyOfRange(ba, off, off + len),
+                                          LATIN1);
+             } else {
+                 return new Result().with(StringLatin1.inflate(ba, off, len), UTF16);
+             }
+        }
         int en = scale(len, cd.maxCharsPerByte());
-        char[] ca = new char[en];
-        if (len == 0)
-            return ca;
-        boolean isTrusted = false;
-        if (System.getSecurityManager() != null) {
-            if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
-                ba =  Arrays.copyOfRange(ba, off, off + len);
-                off = 0;
-            }
+        if (len == 0) {
+            return new Result().with();
+        }
+        if (System.getSecurityManager() != null &&
+            cs.getClass().getClassLoader0() != null) {
+            ba =  Arrays.copyOfRange(ba, off, off + len);
+            off = 0;
         }
         cd.onMalformedInput(CodingErrorAction.REPLACE)
           .onUnmappableCharacter(CodingErrorAction.REPLACE)
           .reset();
+
+        char[] ca = new char[en];
         if (cd instanceof ArrayDecoder) {
             int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
-            return safeTrim(ca, clen, cs, isTrusted);
-        } else {
-            ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
-            CharBuffer cb = CharBuffer.wrap(ca);
-            try {
-                CoderResult cr = cd.decode(bb, cb, true);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-                cr = cd.flush(cb);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-            } catch (CharacterCodingException x) {
-                // Substitution is always enabled,
-                // so this shouldn't happen
-                throw new Error(x);
-            }
-            return safeTrim(ca, cb.position(), cs, isTrusted);
+            return new Result().with(ca, 0, clen);
         }
+        ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        try {
+            CoderResult cr = cd.decode(bb, cb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = cd.flush(cb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            // Substitution is always enabled,
+            // so this shouldn't happen
+            throw new Error(x);
+        }
+        return new Result().with(ca, 0, cb.position());
     }
 
-    static char[] decode(byte[] ba, int off, int len) {
+    static Result decode(byte[] ba, int off, int len) {
         String csn = Charset.defaultCharset().name();
         try {
             // use charset name decode() variant which provides caching.
@@ -273,6 +356,7 @@
     private static class StringEncoder {
         private Charset cs;
         private CharsetEncoder ce;
+        private final boolean isASCIICompatible;
         private final String requestedCharsetName;
         private final boolean isTrusted;
 
@@ -283,6 +367,8 @@
                 .onMalformedInput(CodingErrorAction.REPLACE)
                 .onUnmappableCharacter(CodingErrorAction.REPLACE);
             this.isTrusted = (cs.getClass().getClassLoader0() == null);
+            this.isASCIICompatible = (ce instanceof ArrayEncoder) &&
+                    ((ArrayEncoder)ce).isASCIICompatible();
         }
 
         String charsetName() {
@@ -295,36 +381,186 @@
             return requestedCharsetName;
         }
 
-        byte[] encode(char[] ca, int off, int len) {
+        byte[] encode(byte coder, byte[] val) {
+            // fastpath for ascii compatible
+            if (coder == LATIN1 && isASCIICompatible &&
+                !hasNegatives(val, 0, val.length)) {
+                return Arrays.copyOf(val, val.length);
+            }
+            int len = val.length >> coder;  // assume LATIN1=0/UTF16=1;
             int en = scale(len, ce.maxBytesPerChar());
             byte[] ba = new byte[en];
-            if (len == 0)
+            if (len == 0) {
                 return ba;
+            }
             if (ce instanceof ArrayEncoder) {
-                int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
-                return safeTrim(ba, blen, cs, isTrusted);
-            } else {
-                ce.reset();
-                ByteBuffer bb = ByteBuffer.wrap(ba);
-                CharBuffer cb = CharBuffer.wrap(ca, off, len);
-                try {
-                    CoderResult cr = ce.encode(cb, bb, true);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                    cr = ce.flush(bb);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                } catch (CharacterCodingException x) {
-                    // Substitution is always enabled,
-                    // so this shouldn't happen
-                    throw new Error(x);
+                if (!isTrusted) {
+                    val = Arrays.copyOf(val, val.length);
                 }
-                return safeTrim(ba, bb.position(), cs, isTrusted);
+                int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
+                                              : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
+                if (blen != -1) {
+                    return safeTrim(ba, blen, isTrusted);
+                }
             }
+            char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
+                                           : StringUTF16.toChars(val);
+            ce.reset();
+            ByteBuffer bb = ByteBuffer.wrap(ba);
+            CharBuffer cb = CharBuffer.wrap(ca, 0, len);
+            try {
+                CoderResult cr = ce.encode(cb, bb, true);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+                cr = ce.flush(bb);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+            } catch (CharacterCodingException x) {
+                // Substitution is always enabled,
+                // so this shouldn't happen
+                throw new Error(x);
+            }
+            return safeTrim(ba, bb.position(), isTrusted);
         }
     }
 
-    static byte[] encode(String charsetName, char[] ca, int off, int len)
+    @HotSpotIntrinsicCandidate
+    private static int implEncodeISOArray(byte[] sa, int sp,
+                                          byte[] da, int dp, int len) {
+        int i = 0;
+        for (; i < len; i++) {
+            char c = StringUTF16.getChar(sa, sp++);
+            if (c > '\u00FF')
+                break;
+            da[dp++] = (byte)c;
+        }
+        return i;
+    }
+
+    static byte[] encode8859_1(byte coder, byte[] val) {
+        if (coder == LATIN1) {
+            return Arrays.copyOf(val, val.length);
+        }
+        int len = val.length >> 1;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        int sp = 0;
+        int sl = len;
+        while (sp < sl) {
+            int ret = implEncodeISOArray(val, sp, dst, dp, len);
+            sp = sp + ret;
+            dp = dp + ret;
+            if (ret != len) {
+                char c = StringUTF16.getChar(val, sp++);
+                if (Character.isHighSurrogate(c) && sp < sl &&
+                    Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
+                    sp++;
+                }
+                dst[dp++] = '?';
+                len = sl - sp;
+            }
+        }
+        if (dp == dst.length) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+    static byte[] encodeASCII(byte coder, byte[] val) {
+        if (coder == LATIN1) {
+            byte[] dst = new byte[val.length];
+            for (int i = 0; i < val.length; i++) {
+                if (val[i] < 0) {
+                    dst[i] = '?';
+                } else {
+                    dst[i] = val[i];
+                }
+            }
+            return dst;
+        }
+        int len = val.length >> 1;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        for (int i = 0; i < len; i++) {
+            char c = StringUTF16.getChar(val, i);
+            if (c < 0x80) {
+                dst[dp++] = (byte)c;
+                continue;
+            }
+            if (Character.isHighSurrogate(c) && i + 1 < len &&
+                Character.isLowSurrogate(StringUTF16.getChar(val, i + 1))) {
+                i++;
+            }
+            dst[dp++] = '?';
+        }
+        if (len == dp) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+   static byte[] encodeUTF8(byte coder, byte[] val) {
+        int dp = 0;
+        byte[] dst;
+        if (coder == LATIN1) {
+            dst = new byte[val.length << 1];
+            for (int sp = 0; sp < val.length; sp++) {
+                byte c = val[sp];
+                if (c < 0) {
+                    dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                } else {
+                    dst[dp++] = c;
+                }
+            }
+        } else {
+            int sp = 0;
+            int sl = val.length >> 1;
+            dst = new byte[sl * 3];
+            char c;
+            while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
+                // ascii fast loop;
+                dst[dp++] = (byte)c;
+                sp++;
+            }
+            while (sp < sl) {
+                c = StringUTF16.getChar(val, sp++);
+                if (c < 0x80) {
+                    dst[dp++] = (byte)c;
+                } else if (c < 0x800) {
+                    dst[dp++] = (byte)(0xc0 | (c >> 6));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                } else if (Character.isSurrogate(c)) {
+                    int uc = -1;
+                    char c2;
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
+                        uc = Character.toCodePoint(c, c2);
+                    }
+                    if (uc < 0) {
+                        dst[dp++] = '?';
+                    } else {
+                        dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
+                        dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
+                        dst[dp++] = (byte)(0x80 | ((uc >>  6) & 0x3f));
+                        dst[dp++] = (byte)(0x80 | (uc & 0x3f));
+                        sp++;  // 2 chars
+                    }
+                } else {
+                    // 3 bytes, 16 bits
+                    dst[dp++] = (byte)(0xe0 | ((c >> 12)));
+                    dst[dp++] = (byte)(0x80 | ((c >>  6) & 0x3f));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                }
+            }
+        }
+        if (dp == dst.length) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+    static byte[] encode(String charsetName, byte coder, byte[] val)
         throws UnsupportedEncodingException
     {
         StringEncoder se = deref(encoder);
@@ -334,62 +570,88 @@
             se = null;
             try {
                 Charset cs = lookupCharset(csn);
-                if (cs != null)
+                if (cs != null) {
+                    if (cs == UTF_8) {
+                        return encodeUTF8(coder, val);
+                    } else if (cs == ISO_8859_1) {
+                        return encode8859_1(coder, val);
+                    } else if (cs == US_ASCII) {
+                        return encodeASCII(coder, val);
+                    }
                     se = new StringEncoder(cs, csn);
+                }
             } catch (IllegalCharsetNameException x) {}
-            if (se == null)
+            if (se == null) {
                 throw new UnsupportedEncodingException (csn);
+            }
             set(encoder, se);
         }
-        return se.encode(ca, off, len);
+        return se.encode(coder, val);
     }
 
-    static byte[] encode(Charset cs, char[] ca, int off, int len) {
+    static byte[] encode(Charset cs, byte coder, byte[] val) {
+        if (cs == UTF_8) {
+            return encodeUTF8(coder, val);
+        } else if (cs == ISO_8859_1) {
+            return encode8859_1(coder, val);
+        } else if (cs == US_ASCII) {
+            return encodeASCII(coder, val);
+        }
         CharsetEncoder ce = cs.newEncoder();
+        // fastpath for ascii compatible
+        if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
+                                 ((ArrayEncoder)ce).isASCIICompatible() &&
+                                 !hasNegatives(val, 0, val.length)))) {
+            return Arrays.copyOf(val, val.length);
+        }
+        int len = val.length >> coder;  // assume LATIN1=0/UTF16=1;
         int en = scale(len, ce.maxBytesPerChar());
         byte[] ba = new byte[en];
-        if (len == 0)
+        if (len == 0) {
             return ba;
-        boolean isTrusted = false;
-        if (System.getSecurityManager() != null) {
-            if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
-                ca =  Arrays.copyOfRange(ca, off, off + len);
-                off = 0;
-            }
         }
+        boolean isTrusted = System.getSecurityManager() == null ||
+                            cs.getClass().getClassLoader0() == null;
         ce.onMalformedInput(CodingErrorAction.REPLACE)
           .onUnmappableCharacter(CodingErrorAction.REPLACE)
           .reset();
         if (ce instanceof ArrayEncoder) {
-            int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
-            return safeTrim(ba, blen, cs, isTrusted);
-        } else {
-            ByteBuffer bb = ByteBuffer.wrap(ba);
-            CharBuffer cb = CharBuffer.wrap(ca, off, len);
-            try {
-                CoderResult cr = ce.encode(cb, bb, true);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-                cr = ce.flush(bb);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-            } catch (CharacterCodingException x) {
-                throw new Error(x);
+            if (!isTrusted) {
+                val = Arrays.copyOf(val, val.length);
             }
-            return safeTrim(ba, bb.position(), cs, isTrusted);
+            int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
+                                          : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
+            if (blen != -1) {
+                return safeTrim(ba, blen, isTrusted);
+            }
         }
+        char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
+                                       : StringUTF16.toChars(val);
+        ByteBuffer bb = ByteBuffer.wrap(ba);
+        CharBuffer cb = CharBuffer.wrap(ca, 0, len);
+        try {
+            CoderResult cr = ce.encode(cb, bb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = ce.flush(bb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            throw new Error(x);
+        }
+        return safeTrim(ba, bb.position(), isTrusted);
     }
 
-    static byte[] encode(char[] ca, int off, int len) {
+    static byte[] encode(byte coder, byte[] val) {
         String csn = Charset.defaultCharset().name();
         try {
             // use charset name encode() variant which provides caching.
-            return encode(csn, ca, off, len);
+            return encode(csn, coder, val);
         } catch (UnsupportedEncodingException x) {
             warnUnsupportedCharset(csn);
         }
         try {
-            return encode("ISO-8859-1", ca, off, len);
+            return encode("ISO-8859-1", coder, val);
         } catch (UnsupportedEncodingException x) {
             // If this code is hit during VM initialization, MessageUtils is
             // the only way we will be able to get any kind of error message.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/StringDecoderUTF8.java	Thu Nov 12 14:15:05 2015 -0800
@@ -0,0 +1,235 @@
+/*
+ * 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 java.lang;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.Character.isSurrogate;
+import static java.lang.Character.highSurrogate;
+import static java.lang.Character.lowSurrogate;
+import static java.lang.Character.isSupplementaryCodePoint;
+import static java.lang.StringUTF16.putChar;
+
+class StringDecoderUTF8 extends StringCoding.StringDecoder {
+
+    StringDecoderUTF8(Charset cs, String rcn) {
+        super(cs, rcn);
+    }
+
+    private static boolean isNotContinuation(int b) {
+        return (b & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed3(int b1, int b2, int b3) {
+        return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+               (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed3_2(int b1, int b2) {
+        return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+               (b2 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4(int b2, int b3, int b4) {
+        return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
+               (b4 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4_2(int b1, int b2) {
+        return (b1 == 0xf0 && (b2  < 0x90 || b2 > 0xbf)) ||
+               (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+               (b2 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4_3(int b3) {
+        return (b3 & 0xc0) != 0x80;
+    }
+
+    // for nb == 3/4
+    private static int malformedN(byte[] src, int sp, int nb) {
+        if (nb == 3) {
+            int b1 = src[sp++];
+            int b2 = src[sp++];    // no need to lookup b3
+            return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+                    isNotContinuation(b2)) ? 1 : 2;
+        } else if (nb == 4) { // we don't care the speed here
+            int b1 = src[sp++] & 0xff;
+            int b2 = src[sp++] & 0xff;
+            if (b1 > 0xf4 ||
+                (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
+                (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+                isNotContinuation(b2))
+                return 1;
+            if (isNotContinuation(src[sp++]))
+                return 2;
+            return 3;
+        }
+        assert false;
+        return -1;
+    }
+
+    private static char repl = '\ufffd';
+
+    StringCoding.Result decode(byte[] src, int sp, int len) {
+        return decode(src, sp, len, result);
+    }
+
+    static StringCoding.Result decode(byte[] src, int sp, int len,
+                                      StringCoding.Result ret) {
+        int sl = sp + len;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        if (COMPACT_STRINGS) {   // Latin1 only loop
+            while (sp < sl) {
+                int b1 = src[sp];
+                if (b1 >= 0) {
+                    dst[dp++] = (byte)b1;
+                    sp++;
+                    continue;
+                }
+                if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
+                    sp + 1 < sl) {
+                    int b2 = src[sp + 1];
+                    if (!isNotContinuation(b2)) {
+                        dst[dp++] = (byte)(((b1 << 6) ^ b2)^
+                                           (((byte) 0xC0 << 6) ^
+                                           ((byte) 0x80 << 0)));
+                        sp += 2;
+                        continue;
+                    }
+                }
+                // anything not a latin1, including the repl
+                // we have to go with the utf16
+                break;
+            }
+            if (sp == sl) {
+                if (dp != dst.length) {
+                    dst = Arrays.copyOf(dst, dp);
+                }
+                return ret.with(dst, LATIN1);
+            }
+        }
+        if (dp == 0) {
+            dst = new byte[len << 1];
+        } else {
+            byte[] buf = new byte[len << 1];
+            StringLatin1.inflate(dst, 0, buf, 0, dp);
+            dst = buf;
+        }
+        while (sp < sl) {
+            int b1 = src[sp++];
+            if (b1 >= 0) {
+                putChar(dst, dp++, (char) b1);
+            } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
+                if (sp < sl) {
+                    int b2 = src[sp++];
+                    if (isNotContinuation(b2)) {
+                        putChar(dst, dp++, repl);
+                        sp--;
+                    } else {
+                        putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
+                                                  (((byte) 0xC0 << 6) ^
+                                                  ((byte) 0x80 << 0))));
+                    }
+                    continue;
+                }
+                putChar(dst, dp++, repl);
+                break;
+            } else if ((b1 >> 4) == -2) {
+                if (sp + 1 < sl) {
+                    int b2 = src[sp++];
+                    int b3 = src[sp++];
+                    if (isMalformed3(b1, b2, b3)) {
+                        putChar(dst, dp++, repl);
+                        sp -= 3;
+                        sp += malformedN(src, sp, 3);
+                    } else {
+                        char c = (char)((b1 << 12) ^
+                                        (b2 <<  6) ^
+                                        (b3 ^
+                                         (((byte) 0xE0 << 12) ^
+                                         ((byte) 0x80 <<  6) ^
+                                         ((byte) 0x80 <<  0))));
+                        putChar(dst, dp++, isSurrogate(c) ?  repl : c);
+                    }
+                    continue;
+                }
+                if (sp  < sl && isMalformed3_2(b1, src[sp])) {
+                    putChar(dst, dp++, repl);
+                    continue;
+                }
+                putChar(dst, dp++, repl);
+                break;
+            } else if ((b1 >> 3) == -2) {
+                if (sp + 2 < sl) {
+                    int b2 = src[sp++];
+                    int b3 = src[sp++];
+                    int b4 = src[sp++];
+                    int uc = ((b1 << 18) ^
+                              (b2 << 12) ^
+                              (b3 <<  6) ^
+                              (b4 ^
+                               (((byte) 0xF0 << 18) ^
+                               ((byte) 0x80 << 12) ^
+                               ((byte) 0x80 <<  6) ^
+                               ((byte) 0x80 <<  0))));
+                    if (isMalformed4(b2, b3, b4) ||
+                        !isSupplementaryCodePoint(uc)) { // shortest form check
+                        putChar(dst, dp++, repl);
+                        sp -= 4;
+                        sp += malformedN(src, sp, 4);
+                    } else {
+                        putChar(dst, dp++, highSurrogate(uc));
+                        putChar(dst, dp++, lowSurrogate(uc));
+                    }
+                    continue;
+                }
+                b1 &= 0xff;
+                if (b1 > 0xf4 ||
+                    sp  < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
+                    putChar(dst, dp++, repl);
+                    continue;
+                }
+                sp++;
+                putChar(dst, dp++, repl);
+                if (sp  < sl && isMalformed4_3(src[sp])) {
+                    continue;
+                }
+                break;
+            } else {
+                putChar(dst, dp++, repl);
+            }
+        }
+        if (dp != len) {
+            dst = Arrays.copyOf(dst, dp << 1);
+        }
+        return ret.with(dst, UTF16);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Nov 12 14:15:05 2015 -0800
@@ -0,0 +1,600 @@
+/*
+ * 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 java.lang;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+import java.util.stream.IntStream;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.checkOffset;
+
+final class StringLatin1 {
+
+    public static char charAt(byte[] value, int index) {
+        if (index < 0 || index >= value.length) {
+            throw new StringIndexOutOfBoundsException(index);
+        }
+        return (char)(value[index] & 0xff);
+    }
+
+    public static boolean canEncode(int cp) {
+        return cp >>> 8 == 0;
+    }
+
+    public static int length(byte[] value) {
+        return value.length;
+    }
+
+    public static int codePointAt(byte[] value, int index, int end) {
+        return value[index] & 0xff;
+    }
+
+    public static int codePointBefore(byte[] value, int index) {
+        return value[index - 1] & 0xff;
+    }
+
+    public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+        return endIndex - beginIndex;
+    }
+
+    public static char[] toChars(byte[] value) {
+        char[] dst = new char[value.length];
+        inflate(value, 0, dst, 0, value.length);
+        return dst;
+    }
+
+    public static byte[] inflate(byte[] value, int off, int len) {
+        byte[] ret = StringUTF16.newBytesFor(len);
+        inflate(value, off, ret, 0, len);
+        return ret;
+    }
+
+    public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+    }
+
+    public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
+        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static boolean equals(byte[] value, byte[] other) {
+        if (value.length == other.length) {
+            for (int i = 0; i < value.length; i++) {
+                if (value[i] != other[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareTo(byte[] value, byte[] other) {
+        int len1 = value.length;
+        int len2 = other.length;
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            if (value[k] != other[k]) {
+                return getChar(value, k) - getChar(other, k);
+            }
+        }
+        return len1 - len2;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareToUTF16(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = StringUTF16.length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = StringUTF16.getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    public static int hashCode(byte[] value) {
+        int h = 0;
+        for (byte v : value) {
+            h = 31 * h + (v & 0xff);
+        }
+        return h;
+    }
+
+    public static int indexOf(byte[] value, int ch, int fromIndex) {
+        if (!canEncode(ch)) {
+            return -1;
+        }
+        int max = value.length;
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        } else if (fromIndex >= max) {
+            // Note: fromIndex might be near -1>>>1.
+            return -1;
+        }
+        byte c = (byte)ch;
+        for (int i = fromIndex; i < max; i++) {
+            if (value[i] == c) {
+               return i;
+            }
+        }
+        return -1;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOf(value, value.length, str, str.length, 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+        byte first = str[0];
+        int max = (valueCount - strCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (value[i] != first) {
+                while (++i <= max && value[i] != first);
+            }
+            // Found first character, now look at the rest of value
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + strCount - 1;
+                for (int k = 1; j < end && value[j] == str[k]; j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static int lastIndexOf(byte[] src, int srcCount,
+                                  byte[] tgt, int tgtCount, int fromIndex) {
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
+        char strLastChar = (char)(tgt[strLastIndex] & 0xff);
+
+  startSearchForLastChar:
+        while (true) {
+            while (i >= min && (src[i] & 0xff) != strLastChar) {
+                i--;
+            }
+            if (i < min) {
+                return -1;
+            }
+            int j = i - 1;
+            int start = j - strLastIndex;
+            int k = strLastIndex - 1;
+            while (j > start) {
+                if ((src[j--] & 0xff) != (tgt[k--] & 0xff)) {
+                    i--;
+                    continue startSearchForLastChar;
+                }
+            }
+            return start + 1;
+        }
+    }
+
+    public static int lastIndexOf(final byte[] value, int ch, int fromIndex) {
+        if (!canEncode(ch)) {
+            return -1;
+        }
+        int off  = Math.min(fromIndex, value.length - 1);
+        for (; off >= 0; off--) {
+            if (value[off] == (byte)ch) {
+                return off;
+            }
+        }
+        return -1;
+    }
+
+    public static String replace(byte[] value, char oldChar, char newChar) {
+        if (canEncode(oldChar)) {
+            int len = value.length;
+            int i = -1;
+            while (++i < len) {
+                if (value[i] == (byte)oldChar) {
+                    break;
+                }
+            }
+            if (i < len) {
+                if (canEncode(newChar)) {
+                    byte buf[] = new byte[len];
+                    for (int j = 0; j < i; j++) {    // TBD arraycopy?
+                        buf[j] = value[j];
+                    }
+                    while (i < len) {
+                        byte c = value[i];
+                        buf[i] = (c == (byte)oldChar) ? (byte)newChar : c;
+                        i++;
+                    }
+                    return new String(buf, LATIN1);
+                } else {
+                    byte[] buf = StringUTF16.newBytesFor(len);
+                    // inflate from latin1 to UTF16
+                    inflate(value, 0, buf, 0, i);
+                    while (i < len) {
+                        char c = (char)(value[i] & 0xff);
+                        StringUTF16.putChar(buf, i, (c == oldChar) ? newChar : c);
+                        i++;
+                    }
+                    return new String(buf, UTF16);
+                }
+            }
+        }
+        return null; // for string to return this;
+    }
+
+    // case insensitive
+    public static boolean regionMatchesCI(byte[] value, int toffset,
+                                          byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = (char)(value[toffset++] & 0xff);
+            char c2 = (char)(other[ooffset++] & 0xff);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean regionMatchesCI_UTF16(byte[] value, int toffset,
+                                                byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = (char)(value[toffset++] & 0xff);
+            char c2 = StringUTF16.getChar(other, ooffset++);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static String toLowerCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        final int len = value.length;
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = value[first] & 0xff;
+            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len)
+            return str;
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toLowerCaseEx(str, value, first, locale, true);
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
+                                                       // lowerCase characters.
+        for (int i = first; i < len; i++) {
+            int cp = value[i] & 0xff;
+            cp = Character.toLowerCase(cp);
+            if (!canEncode(cp)) {                      // not a latin1 character
+                return toLowerCaseEx(str, value, first, locale, false);
+            }
+            result[i] = (byte)cp;
+        }
+        return new String(result, LATIN1);
+    }
+
+    private static String toLowerCaseEx(String str, byte[] value,
+                                        int first, Locale locale, boolean localeDependent)
+    {
+        byte[] result = StringUTF16.newBytesFor(value.length);
+        int resultOffset = 0;
+        for (int i = 0; i < first; i++) {
+            StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
+        }
+        for (int i = first; i < value.length; i++) {
+            int srcChar = value[i] & 0xff;
+            int lowerChar;
+            char[] lowerCharArray;
+            if (localeDependent) {
+                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
+            } else {
+                lowerChar = Character.toLowerCase(srcChar);
+            }
+            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
+                StringUTF16.putChar(result, resultOffset++, lowerChar);
+            } else {
+                if (lowerChar == Character.ERROR) {
+                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
+                } else {
+                    lowerCharArray = Character.toChars(lowerChar);
+                }
+                /* Grow result if needed */
+                int mapLen = lowerCharArray.length;
+                if (mapLen > 1) {
+                    byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    StringUTF16.putChar(result, resultOffset++, lowerCharArray[x]);
+                }
+            }
+        }
+        return StringUTF16.newString(result, 0, resultOffset);
+    }
+
+    public static String toUpperCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        final int len = value.length;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++ ) {
+            int cp = value[first] & 0xff;
+            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len) {
+            return str;
+        }
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toUpperCaseEx(str, value, first, locale, true);
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
+                                                       // upperCase characters.
+        for (int i = first; i < len; i++) {
+            int cp = value[i] & 0xff;
+            cp = Character.toUpperCaseEx(cp);
+            if (!canEncode(cp)) {                      // not a latin1 character
+                return toUpperCaseEx(str, value, first, locale, false);
+            }
+            result[i] = (byte)cp;
+        }
+        return new String(result, LATIN1);
+    }
+
+    private static String toUpperCaseEx(String str, byte[] value,
+                                        int first, Locale locale, boolean localeDependent)
+    {
+        byte[] result = StringUTF16.newBytesFor(value.length);
+        int resultOffset = 0;
+        for (int i = 0; i < first; i++) {
+            StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
+        }
+        for (int i = first; i < value.length; i++) {
+            int srcChar = value[i] & 0xff;
+            int upperChar;
+            char[] upperCharArray;
+            if (localeDependent) {
+                upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
+            } else {
+                upperChar = Character.toUpperCaseEx(srcChar);
+            }
+            if (Character.isBmpCodePoint(upperChar)) {
+                StringUTF16.putChar(result, resultOffset++, upperChar);
+            } else {
+                if (upperChar == Character.ERROR) {
+                    if (localeDependent) {
+                        upperCharArray =
+                            ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
+                    } else {
+                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
+                    }
+                } else {
+                    upperCharArray = Character.toChars(upperChar);
+                }
+                /* Grow result if needed */
+                int mapLen = upperCharArray.length;
+                if (mapLen > 1) {
+                    byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    StringUTF16.putChar(result, resultOffset++, upperCharArray[x]);
+                }
+            }
+        }
+        return StringUTF16.newString(result, 0, resultOffset);
+    }
+
+    public static String trim(byte[] value) {
+        int len = value.length;
+        int st = 0;
+        while ((st < len) && ((value[st] & 0xff) <= ' ')) {
+            st++;
+        }
+        while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
+            len--;
+        }
+        return ((st > 0) || (len < value.length)) ?
+            newString(value, st, len - st) : null;
+    }
+
+    public static void putChar(byte[] val, int index, int c) {
+        //assert (canEncode(c));
+        val[index] = (byte)(c);
+    }
+
+    public static char getChar(byte[] val, int index) {
+        return (char)(val[index] & 0xff);
+    }
+
+    public static byte[] toBytes(int[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        for (int i = 0; i < len; i++) {
+            int cp = val[off++];
+            if (!canEncode(cp)) {
+                return null;
+            }
+            ret[i] = (byte)cp;
+        }
+        return ret;
+    }
+
+    public static byte[] toBytes(char c) {
+        return new byte[] { (byte)c };
+    }
+
+    public static String newString(byte[] val, int index, int len) {
+        return new String(Arrays.copyOfRange(val, index, index + len),
+                          LATIN1);
+    }
+
+    public static void fillNull(byte[] val, int index, int end) {
+        Arrays.fill(val, index, end, (byte)0);
+    }
+
+    // inflatedCopy byte[] -> char[]
+    @HotSpotIntrinsicCandidate
+    private static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            dst[dstOff++] = (char)(src[srcOff++] & 0xff);
+        }
+    }
+
+    // inflatedCopy byte[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
+        }
+    }
+
+    static class CharsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CharsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length, acs);
+        }
+
+        CharsSpliterator(byte[] 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 CharsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            byte[] 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] & 0xff); } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                action.accept(array[index++] & 0xff);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        checkOffset(srcEnd, val.length);
+        getChars(val, srcBegin, srcEnd, dst, dstBegin);
+    }
+
+    public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) {
+        checkOffset(count, val.length);
+        checkOffset(dstOff + count, dst.length >> 1);  // dst is utf16
+        inflate(val, 0, dst, dstOff, count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Thu Nov 12 14:15:05 2015 -0800
@@ -0,0 +1,971 @@
+/*
+ * 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 java.lang;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import static java.lang.String.UTF16;
+import static java.lang.String.LATIN1;
+import static java.lang.String.checkIndex;
+import static java.lang.String.checkOffset;
+
+final class StringUTF16 {
+
+    public static byte[] newBytesFor(int len) {
+        if (len < 0) {
+            throw new NegativeArraySizeException();
+        }
+        if (len > MAX_LENGTH) {
+            throw new OutOfMemoryError("UTF16 String size is " + len +
+                                       ", should be less than " + MAX_LENGTH);
+        }
+        return new byte[len << 1];
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static void putChar(byte[] val, int index, int c) {
+        index <<= 1;
+        val[index++] = (byte)(c >> HI_BYTE_SHIFT);
+        val[index]   = (byte)(c >> LO_BYTE_SHIFT);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static char getChar(byte[] val, int index) {
+        index <<= 1;
+        return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
+                      ((val[index]   & 0xff) << LO_BYTE_SHIFT));
+    }
+
+    public static char charAt(byte[] value, int index) {
+        if (index < 0 || index >= value.length >> 1) {
+            throw new StringIndexOutOfBoundsException(index);
+        }
+        return getChar(value, index);
+    }
+
+    public static int length(byte[] value) {
+        return value.length >> 1;
+    }
+
+    public static int codePointAt(byte[] value, int index, int end) {
+        char c1 = getChar(value, index);
+        if (Character.isHighSurrogate(c1) && ++index < end) {
+            char c2 = getChar(value, index);
+            if (Character.isLowSurrogate(c2)) {
+               return Character.toCodePoint(c1, c2);
+            }
+        }
+        return c1;
+    }
+
+    public static int codePointBefore(byte[] value, int index) {
+        char c2 = getChar(value, --index);
+        if (Character.isLowSurrogate(c2) && index > 0) {
+            char c1 = getChar(value, --index);
+            if (Character.isHighSurrogate(c1)) {
+               return Character.toCodePoint(c1, c2);
+            }
+        }
+        return c2;
+    }
+
+    public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+        int count = endIndex - beginIndex;
+        for (int i = beginIndex; i < endIndex; ) {
+            if (Character.isHighSurrogate(getChar(value, i++)) &&
+                i < endIndex &&
+                Character.isLowSurrogate(getChar(value, i))) {
+                count--;
+                i++;
+            }
+        }
+        return count;
+    }
+
+    public static char[] toChars(byte[] value) {
+        char[] dst = new char[value.length >> 1];
+        getChars(value, 0, dst.length, dst, 0);
+        return dst;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static byte[] toBytes(char[] value, int off, int len) {
+        byte[] val = newBytesFor(len);
+        for (int i = 0; i < len; i++) {
+            putChar(val, i, value[off++]);
+        }
+        return val;
+    }
+
+    public static byte[] compress(char[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        if (compress(val, off, ret, 0, len) == len) {
+            return ret;
+        }
+        return null;
+    }
+
+    public static byte[] compress(byte[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        if (compress(val, off, ret, 0, len) == len) {
+            return ret;
+        }
+        return null;
+    }
+
+    // compressedCopy char[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            int c = src[srcOff++];
+            if (c >>> 8 != 0) {
+                return 0;
+            }
+            dst[dstOff++] = (byte)c;
+        }
+        return len;
+    }
+
+    // compressedCopy byte[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            int c = getChar(src, srcOff++);
+            if (c >>> 8 != 0) {
+                return 0;
+            }
+            dst[dstOff++] = (byte)c;
+        }
+        return len;
+    }
+
+    public static byte[] toBytes(int[] val, int index, int len) {
+        final int end = index + len;
+        // Pass 1: Compute precise size of char[]
+        int n = len;
+        for (int i = index; i < end; i++) {
+            int cp = val[i];
+            if (Character.isBmpCodePoint(cp))
+                continue;
+            else if (Character.isValidCodePoint(cp))
+                n++;
+            else throw new IllegalArgumentException(Integer.toString(cp));
+        }
+        // Pass 2: Allocate and fill in <high, low> pair
+        byte[] buf = newBytesFor(n);
+        for (int i = index, j = 0; i < end; i++, j++) {
+            int cp = val[i];
+            if (Character.isBmpCodePoint(cp)) {
+                putChar(buf, j, cp);
+            } else {
+                putChar(buf, j++, Character.highSurrogate(cp));
+                putChar(buf, j, Character.lowSurrogate(cp));
+            }
+        }
+        return buf;
+    }
+
+    public static byte[] toBytes(char c) {
+        byte[] result = new byte[2];
+        putChar(result, 0, c);
+        return result;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        for (int i = srcBegin; i < srcEnd; i++) {
+            dst[dstBegin++] = getChar(value, i);
+        }
+    }
+
+    /* @see java.lang.String.getBytes(int, int, byte[], int) */
+    public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
+        srcBegin <<= 1;
+        srcEnd <<= 1;
+        for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) {
+            dst[dstBegin++] = value[i];
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static boolean equals(byte[] value, byte[] other) {
+        if (value.length == other.length) {
+            int len = value.length >> 1;
+            for (int i = 0; i < len; i++) {
+                if (getChar(value, i) != getChar(other, i)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareTo(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareToLatin1(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = StringLatin1.length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = StringLatin1.getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    public static int hashCode(byte[] value) {
+        int h = 0;
+        int length = value.length >> 1;
+        for (int i = 0; i < length; i++) {
+            h = 31 * h + getChar(value, i);
+        }
+        return h;
+    }
+
+    public static int indexOf(byte[] value, int ch, int fromIndex) {
+        int max = value.length >> 1;
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        } else if (fromIndex >= max) {
+            // Note: fromIndex might be near -1>>>1.
+            return -1;
+        }
+        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            // handle most cases here (ch is a BMP code point or a
+            // negative value (invalid code point))
+            return indexOfChar(value, ch, fromIndex, max);
+        } else {
+            return indexOfSupplementary(value, ch, fromIndex, max);
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOf(value, length(value), str, length(str), 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+        char first = getChar(str, 0);
+        int max = (valueCount - strCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (getChar(value, i) != first) {
+                while (++i <= max && getChar(value, i) != first);
+            }
+            // Found first character, now look at the rest of value
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + strCount - 1;
+                for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Handles indexOf Latin1 substring in UTF16 string.
+     */
+    @HotSpotIntrinsicCandidate
+    public static int indexOfLatin1(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOfLatin1(value, length(value), str, str.length, 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
+        char first = (char)(tgt[0] & 0xff);
+        int max = (srcCount - tgtCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (getChar(src, i) != first) {
+                while (++i <= max && getChar(src, i) != first);
+            }
+            // Found first character, now look at the rest of v2
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + tgtCount - 1;
+                for (int k = 1;
+                     j < end && getChar(src, j) == (tgt[k] & 0xff);
+                     j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    @HotSpotIntrinsicCandidate
+    private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
+        for (int i = fromIndex; i < max; i++) {
+            if (getChar(value, i) == ch) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Handles (rare) calls of indexOf with a supplementary character.
+     */
+    private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) {
+        if (Character.isValidCodePoint(ch)) {
+            final char hi = Character.highSurrogate(ch);
+            final char lo = Character.lowSurrogate(ch);
+            for (int i = fromIndex; i < max - 1; i++) {
+                if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static int lastIndexOf(byte[] src, int srcCount,
+                                  byte[] tgt, int tgtCount, int fromIndex) {
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
+        char strLastChar = getChar(tgt, strLastIndex);
+
+    startSearchForLastChar:
+        while (true) {
+            while (i >= min && getChar(src, i) != strLastChar) {
+                i--;
+            }
+            if (i < min) {
+                return -1;
+            }
+            int j = i - 1;
+            int start = j - strLastIndex;
+            int k = strLastIndex - 1;
+            while (j > start) {
+                if (getChar(src, j--) != getChar(tgt, k--)) {
+                    i--;
+                    continue startSearchForLastChar;
+                }
+            }
+            return start + 1;
+        }
+    }
+
+    public static int lastIndexOf(byte[] value, int ch, int fromIndex) {
+        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            // handle most cases here (ch is a BMP code point or a
+            // negative value (invalid code point))
+            int i = Math.min(fromIndex, (value.length >> 1) - 1);
+            for (; i >= 0; i--) {
+                if (getChar(value, i) == ch) {
+                    return i;
+                }
+            }
+            return -1;
+        } else {
+            return lastIndexOfSupplementary(value, ch, fromIndex);
+        }
+    }
+
+    /**
+     * Handles (rare) calls of lastIndexOf with a supplementary character.
+     */
+    private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) {
+        if (Character.isValidCodePoint(ch)) {
+            char hi = Character.highSurrogate(ch);
+            char lo = Character.lowSurrogate(ch);
+            int i = Math.min(fromIndex, (value.length >> 1) - 2);
+            for (; i >= 0; i--) {
+                if (getChar(value, i) == hi && getChar(value, i + 1) == lo) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static String replace(byte[] value, char oldChar, char newChar) {
+        int len = value.length >> 1;
+        int i = -1;
+        while (++i < len) {
+            if (getChar(value, i) == oldChar) {
+                break;
+            }
+        }
+        if (i < len) {
+            byte buf[] = new byte[value.length];
+            for (int j = 0; j < i; j++) {
+                putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
+            }
+            while (i < len) {
+                char c = getChar(value, i);
+                putChar(buf, i, c == oldChar ? newChar : c);
+                i++;
+           }
+           // Check if we should try to compress to latin1
+           if (String.COMPACT_STRINGS &&
+               !StringLatin1.canEncode(oldChar) &&
+               StringLatin1.canEncode(newChar)) {
+               byte[] val = compress(buf, 0, len);
+               if (val != null) {
+                   return new String(val, LATIN1);
+               }
+           }
+           return new String(buf, UTF16);
+        }
+        return null;
+    }
+
+    public static boolean regionMatchesCI(byte[] value, int toffset,
+                                          byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = getChar(value, toffset++);
+            char c2 = getChar(other, ooffset++);
+            if (c1 == c2) {
+                continue;
+            }
+            // try converting both characters to uppercase.
+            // If the results match, then the comparison scan should
+            // continue.
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            // Unfortunately, conversion to uppercase does not work properly
+            // for the Georgian alphabet, which has strange rules about case
+            // conversion.  So we need to make one last check before
+            // exiting.
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,
+                                                 byte[] other, int ooffset,
+                                                 int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = getChar(value, toffset++);
+            char c2 = (char)(other[ooffset++] & 0xff);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static String toLowerCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        boolean hasSurr = false;
+        final int len = value.length >> 1;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = (int)getChar(value, first);
+            if (Character.isSurrogate((char)cp)) {
+                hasSurr = true;
+                break;
+            }
+            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len)
+            return str;
+        byte[] result = new byte[value.length];
+        System.arraycopy(value, 0, result, 0, first << 1);  // Just copy the first few
+                                                            // lowerCase characters.
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toLowerCaseEx(str, value, result, first, locale, true);
+        }
+        if (hasSurr) {
+            return toLowerCaseEx(str, value, result, first, locale, false);
+        }
+        int bits = 0;
+        for (int i = first; i < len; i++) {
+            int cp = (int)getChar(value, i);
+            if (cp == '\u03A3' ||                       // GREEK CAPITAL LETTER SIGMA
+                Character.isSurrogate((char)cp)) {
+                return toLowerCaseEx(str, value, result, i, locale, false);
+            }
+            if (cp == '\u0130') {                       // LATIN CAPITAL LETTER I WITH DOT ABOVE
+                return toLowerCaseEx(str, value, result, i, locale, true);
+            }
+            cp = Character.toLowerCase(cp);
+            if (!Character.isBmpCodePoint(cp)) {
+                return toLowerCaseEx(str, value, result, i, locale, false);
+            }
+            bits |= cp;
+            putChar(result, i, cp);
+        }
+        if (bits >>> 8 != 0) {
+            return new String(result, UTF16);
+        } else {
+            return newString(result, 0, len);
+        }
+    }
+
+    private static String toLowerCaseEx(String str, byte[] value,
+                                        byte[] result, int first, Locale locale,
+                                        boolean localeDependent) {
+        int resultOffset = first;
+        int length = value.length >> 1;
+        int srcCount;
+        for (int i = first; i < length; i += srcCount) {
+            int srcChar = getChar(value, i);
+            int lowerChar;
+            char[] lowerCharArray;
+            srcCount = 1;
+            if (Character.isSurrogate((char)srcChar)) {
+                srcChar = codePointAt(value, i, length);
+                srcCount = Character.charCount(srcChar);
+            }
+            if (localeDependent ||
+                srcChar == '\u03A3' ||  // GREEK CAPITAL LETTER SIGMA
+                srcChar == '\u0130') {  // LATIN CAPITAL LETTER I WITH DOT ABOVE
+                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
+            } else {
+                lowerChar = Character.toLowerCase(srcChar);
+            }
+            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
+                putChar(result, resultOffset++, lowerChar);
+            } else {
+                if (lowerChar == Character.ERROR) {
+                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
+                } else {
+                    lowerCharArray = Character.toChars(lowerChar);
+                }
+                /* Grow result if needed */
+                int mapLen = lowerCharArray.length;
+                if (mapLen > srcCount) {
+                    byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    putChar(result, resultOffset++, lowerCharArray[x]);
+                }
+            }
+        }
+        return newString(result, 0, resultOffset);
+    }
+
+    public static String toUpperCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        boolean hasSurr = false;
+        final int len = value.length >> 1;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = (int)getChar(value, first);
+            if (Character.isSurrogate((char)cp)) {
+                hasSurr = true;
+                break;
+            }
+            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len) {
+            return str;
+        }
+        byte[] result = new byte[value.length];
+        System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
+                                                           // upperCase characters.
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toUpperCaseEx(str, value, result, first, locale, true);
+        }
+        if (hasSurr) {
+            return toUpperCaseEx(str, value, result, first, locale, false);
+        }
+        int bits = 0;
+        for (int i = first; i < len; i++) {
+            int cp = (int)getChar(value, i);
+            if (Character.isSurrogate((char)cp)) {
+                return toUpperCaseEx(str, value, result, i, locale, false);
+            }
+            cp = Character.toUpperCaseEx(cp);
+            if (!Character.isBmpCodePoint(cp)) {    // Character.ERROR is not bmp
+                return toUpperCaseEx(str, value, result, i, locale, false);
+            }
+            bits |= cp;
+            putChar(result, i, cp);
+        }
+        if (bits >>> 8 != 0) {
+            return new String(result, UTF16);
+        } else {
+            return newString(result, 0, len);
+        }
+    }
+
+    private static String toUpperCaseEx(String str, byte[] value,
+                                        byte[] result, int first,
+                                        Locale locale, boolean localeDependent)
+    {
+        int resultOffset = first;
+        int length = value.length >> 1;
+        int srcCount;
+        for (int i = first; i < length; i += srcCount) {
+            int srcChar = getChar(value, i);
+            int upperChar;
+            char[] upperCharArray;
+            srcCount = 1;
+            if (Character.isSurrogate((char)srcChar)) {
+                srcChar = codePointAt(value, i, length);
+                srcCount = Character.charCount(srcChar);
+            }
+            if (localeDependent) {
+                upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
+            } else {
+                upperChar = Character.toUpperCaseEx(srcChar);
+            }
+            if (Character.isBmpCodePoint(upperChar)) {
+                putChar(result, resultOffset++, upperChar);
+            } else {
+                if (upperChar == Character.ERROR) {
+                    if (localeDependent) {
+                        upperCharArray =
+                            ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
+                    } else {
+                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
+                    }
+                } else {
+                    upperCharArray = Character.toChars(upperChar);
+                }
+                /* Grow result if needed */
+                int mapLen = upperCharArray.length;
+                if (mapLen > srcCount) {
+                    byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                 }
+                 for (int x = 0; x < mapLen; ++x) {
+                    putChar(result, resultOffset++, upperCharArray[x]);
+                 }
+            }
+        }
+        return newString(result, 0, resultOffset);
+    }
+
+    public static String trim(byte[] value) {
+        int length = value.length >> 1;
+        int len = length;
+        int st = 0;
+        while (st < len && getChar(value, st) <= ' ') {
+            st++;
+        }
+        while (st < len && getChar(value, len - 1) <= ' ') {
+            len--;
+        }
+        return ((st > 0) || (len < length )) ?
+            new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
+            null;
+    }
+
+    public static void putChars(byte[] val, int index, char[] str, int off, int end) {
+        while (off < end) {
+            putChar(val, index++, str[off++]);
+        }
+    }
+
+    public static String newString(byte[] val, int index, int len) {
+        if (String.COMPACT_STRINGS) {
+            byte[] buf = compress(val, index, len);
+            if (buf != null) {
+                return new String(buf, LATIN1);
+            }
+        }
+        int last = index + len;
+        return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
+    }
+
+    public static void fillNull(byte[] val, int index, int end) {
+        Arrays.fill(val, index << 1, end << 1, (byte)0);
+    }
+
+    static class CharsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CharsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+        }
+
+        CharsSpliterator(byte[] 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 CharsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if (((a = array).length >> 1) >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do { action.accept(getChar(a, i)); } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                action.accept(getChar(array, index++));
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    static class CodePointsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CodePointsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+        }
+
+        CodePointsSpliterator(byte[] 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(getChar(array, mid)) &&
+                Character.isHighSurrogate(getChar(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) {
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if (((a = array).length >> 1) >= (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(byte[] a, int i, int hi, IntConsumer action) {
+            char c1 = getChar(a, i++);
+            int cp = c1;
+            if (Character.isHighSurrogate(c1) && i < hi) {
+                char c2 = getChar(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;
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        checkOffset(srcEnd, val.length >> 1);
+        getChars(val, srcBegin, srcEnd, dst, dstBegin);
+    }
+
+    public static void putCharSB(byte[] val, int index, int c) {
+        checkIndex(index, val.length >> 1);
+        putChar(val, index, c);
+    }
+
+    public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
+        checkOffset(index + end - off, val.length >> 1);
+        putChars(val, index, ca, off, end);
+    }
+
+    public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
+        checkOffset(index + end - off, val.length >> 1);
+        for (int i = off; i < end; i++) {
+            putChar(val, index++, s.charAt(i));
+        }
+    }
+
+    public static int codePointAtSB(byte[] val, int index, int end) {
+        checkOffset(end, val.length >> 1);
+        return codePointAt(val, index, end);
+    }
+
+    public static int codePointBeforeSB(byte[] val, int index) {
+        checkOffset(index, val.length >> 1);
+        return codePointBefore(val, index);
+    }
+
+    public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
+        checkOffset(endIndex, val.length >> 1);
+        return codePointCount(val, beginIndex, endIndex);
+    }
+
+    public static String newStringSB(byte[] val, int index, int len) {
+        checkOffset(index + len, val.length >> 1);
+        return newString(val, index, len);
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    private static native boolean isBigEndian();
+
+    static final int HI_BYTE_SHIFT;
+    static final int LO_BYTE_SHIFT;
+    static {
+        if (isBigEndian()) {
+            HI_BYTE_SHIFT = 8;
+            LO_BYTE_SHIFT = 0;
+        } else {
+            HI_BYTE_SHIFT = 0;
+            LO_BYTE_SHIFT = 8;
+        }
+    }
+
+    static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
+}
--- a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Nov 12 14:15:05 2015 -0800
@@ -34,14 +34,16 @@
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Field;
 import java.util.Arrays;
-import java.util.HashMap;
+import java.util.function.Function;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
 
+import jdk.internal.org.objectweb.asm.FieldVisitor;
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.Wrapper;
 
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Type;
 
 /**
  * The flavor of method handle which emulates an invoke instruction
@@ -217,7 +219,7 @@
         /*non-public*/ int fieldCount() {
             return 1;
         }
-        /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
+        /*non-public*/ static final SpeciesData SPECIES_DATA = new SpeciesData("L", Species_L.class);
         /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
             return new Species_L(mt, lf, argL0);
         }
@@ -335,7 +337,7 @@
 
         static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
 
-        private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
+        SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
             this.typeChars = types;
             this.typeCodes = basicTypes(types);
             this.clazz = clazz;
@@ -355,26 +357,14 @@
             assert(!INIT_DONE);
             if (constructor() == null) {
                 String types = typeChars;
+                CACHE.put(types, this);
                 Factory.makeCtors(clazz, types, this.constructor);
                 Factory.makeGetters(clazz, types, this.getters);
                 Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
             }
         }
 
-        private SpeciesData(String typeChars) {
-            // Placeholder only.
-            this.typeChars = typeChars;
-            this.typeCodes = basicTypes(typeChars);
-            this.clazz = null;
-            this.constructor = null;
-            this.getters = null;
-            this.nominalGetters = null;
-            this.extensions = null;
-        }
-        private boolean isPlaceholder() { return clazz == null; }
-
-        private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
-        static { CACHE.put("", EMPTY); }  // make bootstrap predictable
+        private static final ConcurrentMap<String, SpeciesData> CACHE = new ConcurrentHashMap<>();
         private static final boolean INIT_DONE;  // set after <clinit> finishes...
 
         SpeciesData extendWith(byte type) {
@@ -390,62 +380,52 @@
         }
 
         private static SpeciesData get(String types) {
-            // Acquire cache lock for query.
-            SpeciesData d = lookupCache(types);
-            if (!d.isPlaceholder())
-                return d;
-            synchronized (d) {
-                // Use synch. on the placeholder to prevent multiple instantiation of one species.
-                // Creating this class forces a recursive call to getForClass.
-                if (lookupCache(types).isPlaceholder())
-                    Factory.generateConcreteBMHClass(types);
-            }
-            // Reacquire cache lock.
-            d = lookupCache(types);
-            // Class loading must have upgraded the cache.
-            assert(d != null && !d.isPlaceholder());
-            return d;
-        }
-        static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
-            // clazz is a new class which is initializing its SPECIES_DATA field
-            return updateCache(types, new SpeciesData(types, clazz));
-        }
-        private static synchronized SpeciesData lookupCache(String types) {
-            SpeciesData d = CACHE.get(types);
-            if (d != null)  return d;
-            d = new SpeciesData(types);
-            assert(d.isPlaceholder());
-            CACHE.put(types, d);
-            return d;
-        }
-        private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
-            SpeciesData d2;
-            assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
-            assert(!d.isPlaceholder());
-            CACHE.put(types, d);
-            return d;
+            return CACHE.computeIfAbsent(types, new Function<String, SpeciesData>() {
+                @Override
+                public SpeciesData apply(String types) {
+                    Class<? extends BoundMethodHandle> bmhcl = Factory.getConcreteBMHClass(types);
+                    // SpeciesData instantiation may throw VirtualMachineError because of
+                    // code cache overflow...
+                    SpeciesData speciesData = new SpeciesData(types, bmhcl);
+                    // CHM.computeIfAbsent ensures only one SpeciesData will be set
+                    // successfully on the concrete BMH class if ever
+                    Factory.setSpeciesDataToConcreteBMHClass(bmhcl, speciesData);
+                    // the concrete BMH class is published via SpeciesData instance
+                    // returned here only after it's SPECIES_DATA field is set
+                    return speciesData;
+                }
+            });
         }
 
-        static {
-            // pre-fill the BMH speciesdata cache with BMH's inner classes
-            final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
+        /**
+         * This is to be called when assertions are enabled. It checks whether SpeciesData for all of the statically
+         * defined species subclasses of BoundMethodHandle has been added to the SpeciesData cache. See below in the
+         * static initializer for
+         */
+        static boolean speciesDataCachePopulated() {
+            Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
             try {
                 for (Class<?> c : rootCls.getDeclaredClasses()) {
                     if (rootCls.isAssignableFrom(c)) {
                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
-                        SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
+                        SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh);
                         assert(d != null) : cbmh.getName();
                         assert(d.clazz == cbmh);
-                        assert(d == lookupCache(d.typeChars));
+                        assert(CACHE.get(d.typeChars) == d);
                     }
                 }
             } catch (Throwable e) {
                 throw newInternalError(e);
             }
+            return true;
+        }
 
-            for (SpeciesData d : CACHE.values()) {
-                d.initForBootstrap();
-            }
+        static {
+            // Pre-fill the BMH species-data cache with EMPTY and all BMH's inner subclasses.
+            EMPTY.initForBootstrap();
+            Species_L.SPECIES_DATA.initForBootstrap();
+            // check that all static SpeciesData instances have been initialized
+            assert speciesDataCachePopulated();
             // Note:  Do not simplify this, because INIT_DONE must not be
             // a compile-time constant during bootstrapping.
             INIT_DONE = Boolean.TRUE;
@@ -479,6 +459,7 @@
         static final String BMH_SIG  = "L"+BMH+";";
         static final String SPECIES_DATA     = "java/lang/invoke/BoundMethodHandle$SpeciesData";
         static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
+        static final String STABLE_SIG       = "Ljava/lang/invoke/Stable;";
 
         static final String SPECIES_PREFIX_NAME = "Species_";
         static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
@@ -493,6 +474,26 @@
 
         static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
 
+        static final ConcurrentMap<String, Class<? extends BoundMethodHandle>> CLASS_CACHE = new ConcurrentHashMap<>();
+
+        /**
+         * Get a concrete subclass of BMH for a given combination of bound types.
+         *
+         * @param types the type signature, wherein reference types are erased to 'L'
+         * @return the concrete BMH class
+         */
+        static Class<? extends BoundMethodHandle> getConcreteBMHClass(String types) {
+            // CHM.computeIfAbsent ensures generateConcreteBMHClass is called
+            // only once per key.
+            return CLASS_CACHE.computeIfAbsent(
+                types, new Function<String, Class<? extends BoundMethodHandle>>() {
+                    @Override
+                    public Class<? extends BoundMethodHandle> apply(String types) {
+                        return generateConcreteBMHClass(types);
+                    }
+                });
+        }
+
         /**
          * Generate a concrete subclass of BMH for a given combination of bound types.
          *
@@ -529,7 +530,7 @@
          *     }
          *     final SpeciesData speciesData() { return SPECIES_DATA; }
          *     final int fieldCount() { return 3; }
-         *     static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
+         *     &#64;Stable static SpeciesData SPECIES_DATA; // injected afterwards
          *     static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
          *         return new Species_LLI(mt, lf, argL0, argL1, argI2);
          *     }
@@ -568,7 +569,9 @@
             cw.visitSource(sourceFile, null);
 
             // emit static types and SPECIES_DATA fields
-            cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
+            FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null);
+            fw.visitAnnotation(STABLE_SIG, true);
+            fw.visitEnd();
 
             // emit bound argument fields
             for (int i = 0; i < types.length(); ++i) {
@@ -694,17 +697,6 @@
                 mv.visitEnd();
             }
 
-            // emit class initializer
-            mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
-            mv.visitCode();
-            mv.visitLdcInsn(types);
-            mv.visitLdcInsn(Type.getObjectType(className));
-            mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false);
-            mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
-            mv.visitInsn(RETURN);
-            mv.visitMaxs(0, 0);
-            mv.visitEnd();
-
             cw.visitEnd();
 
             // load class
@@ -715,7 +707,6 @@
                 UNSAFE.defineClass(className, classFile, 0, classFile.length,
                                    BoundMethodHandle.class.getClassLoader(), null)
                     .asSubclass(BoundMethodHandle.class);
-            UNSAFE.ensureClassInitialized(bmhClass);
 
             return bmhClass;
         }
@@ -785,7 +776,7 @@
         // Auxiliary methods.
         //
 
-        static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
+        static SpeciesData getSpeciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
             try {
                 Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
                 return (SpeciesData) F_SPECIES_DATA.get(null);
@@ -794,6 +785,16 @@
             }
         }
 
+        static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) {
+            try {
+                Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
+                assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
+                F_SPECIES_DATA.set(null, speciesData);
+            } catch (ReflectiveOperationException ex) {
+                throw newInternalError(ex);
+            }
+        }
+
         /**
          * Field names in concrete BMHs adhere to this pattern:
          * arg + type + index
--- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Nov 12 14:15:05 2015 -0800
@@ -25,7 +25,7 @@
 
 package java.lang.invoke;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import sun.invoke.util.VerifyAccess;
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Nov 12 14:15:05 2015 -0800
@@ -27,7 +27,7 @@
 
 import jdk.internal.org.objectweb.asm.*;
 import sun.invoke.util.BytecodeDescriptor;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.security.action.GetPropertyAction;
 
 import java.io.FilePermission;
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Nov 12 14:15:05 2015 -0800
@@ -775,7 +775,7 @@
         // Sample classes from each package we are willing to bind to statically:
         java.lang.Object.class,
         java.util.Arrays.class,
-        sun.misc.Unsafe.class
+        jdk.internal.misc.Unsafe.class
         //MethodHandle.class already covered
     };
 
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java	Thu Nov 12 14:15:05 2015 -0800
@@ -694,8 +694,11 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(clazz, getReferenceKind(), name, getType());
+        // Avoid autoboxing getReferenceKind(), since this is used early and will force
+        // early initialization of Byte$ByteCache
+        return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType());
     }
+
     @Override
     public boolean equals(Object that) {
         return (that instanceof MemberName && this.equals((MemberName)that));
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Nov 12 14:15:05 2015 -0800
@@ -50,7 +50,7 @@
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
-    /// Field layout queries parallel to sun.misc.Unsafe:
+    /// Field layout queries parallel to jdk.internal.misc.Unsafe:
     static native long objectFieldOffset(MemberName self);  // e.g., returns vmindex
     static native long staticFieldOffset(MemberName self);  // e.g., returns vmindex
     static native Object staticFieldBase(MemberName self);  // e.g., returns clazz
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Nov 12 14:15:05 2015 -0800
@@ -27,7 +27,7 @@
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * This class consists exclusively of static names internal to the
--- a/src/java.base/share/classes/java/math/BigDecimal.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/math/BigDecimal.java	Thu Nov 12 14:15:05 2015 -0800
@@ -3726,12 +3726,12 @@
     }
 
     private static class UnsafeHolder {
-        private static final sun.misc.Unsafe unsafe;
+        private static final jdk.internal.misc.Unsafe unsafe;
         private static final long intCompactOffset;
         private static final long intValOffset;
         static {
             try {
-                unsafe = sun.misc.Unsafe.getUnsafe();
+                unsafe = jdk.internal.misc.Unsafe.getUnsafe();
                 intCompactOffset = unsafe.objectFieldOffset
                     (BigDecimal.class.getDeclaredField("intCompact"));
                 intValOffset = unsafe.objectFieldOffset
--- a/src/java.base/share/classes/java/math/BigInteger.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/math/BigInteger.java	Thu Nov 12 14:15:05 2015 -0800
@@ -4526,12 +4526,12 @@
 
     // Support for resetting final fields while deserializing
     private static class UnsafeHolder {
-        private static final sun.misc.Unsafe unsafe;
+        private static final jdk.internal.misc.Unsafe unsafe;
         private static final long signumOffset;
         private static final long magOffset;
         static {
             try {
-                unsafe = sun.misc.Unsafe.getUnsafe();
+                unsafe = jdk.internal.misc.Unsafe.getUnsafe();
                 signumOffset = unsafe.objectFieldOffset
                     (BigInteger.class.getDeclaredField("signum"));
                 magOffset = unsafe.objectFieldOffset
--- a/src/java.base/share/classes/java/net/Inet6Address.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/net/Inet6Address.java	Thu Nov 12 14:15:05 2015 -0800
@@ -576,11 +576,11 @@
     };
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
 
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                     Inet6Address.class.getDeclaredField("holder6"));
             UNSAFE = unsafe;
--- a/src/java.base/share/classes/java/net/InetAddress.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Thu Nov 12 14:15:05 2015 -0800
@@ -29,6 +29,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.ServiceLoader;
 import java.security.AccessController;
 import java.io.ObjectStreamException;
@@ -733,7 +734,7 @@
      */
     public String toString() {
         String hostName = holder().getHostName();
-        return ((hostName != null) ? hostName : "")
+        return Objects.toString(hostName, "")
             + "/" + getHostAddress();
     }
 
@@ -1493,11 +1494,11 @@
     }
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
 
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                 InetAddress.class.getDeclaredField("holder")
             );
--- a/src/java.base/share/classes/java/net/InetSocketAddress.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/net/InetSocketAddress.java	Thu Nov 12 14:15:05 2015 -0800
@@ -303,10 +303,10 @@
     }
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                     InetSocketAddress.class.getDeclaredField("holder"));
             UNSAFE = unsafe;
--- a/src/java.base/share/classes/java/net/SocketOptions.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/net/SocketOptions.java	Thu Nov 12 14:15:05 2015 -0800
@@ -61,21 +61,21 @@
      * If the requested option is binary, it can be set using this method by
      * a java.lang.Boolean:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(true));
+     * s.setOption(TCP_NODELAY, Boolean.TRUE);
      *    // OK - enables TCP_NODELAY, a binary option
      * </PRE>
      * <BR>
-     * Any option can be disabled using this method with a Boolean(false):
+     * Any option can be disabled using this method with a Boolean.FALSE:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(false));
+     * s.setOption(TCP_NODELAY, Boolean.FALSE);
      *    // OK - disables TCP_NODELAY
-     * s.setOption(SO_LINGER, new Boolean(false));
+     * s.setOption(SO_LINGER, Boolean.FALSE);
      *    // OK - disables SO_LINGER
      * </PRE>
      * <BR>
      * For an option that has a notion of on and off, and requires
      * a non-boolean parameter, setting its value to anything other than
-     * <I>Boolean(false)</I> implicitly enables it.
+     * <I>Boolean.FALSE</I> implicitly enables it.
      * <BR>
      * Throws SocketException if the option is unrecognized,
      * the socket is closed, or some low-level error occurred
@@ -91,8 +91,8 @@
 
     /**
      * Fetch the value of an option.
-     * Binary options will return java.lang.Boolean(true)
-     * if enabled, java.lang.Boolean(false) if disabled, e.g.:
+     * Binary options will return java.lang.Boolean.TRUE
+     * if enabled, java.lang.Boolean.FALSE if disabled, e.g.:
      * <BR><PRE>
      * SocketImpl s;
      * ...
@@ -105,13 +105,13 @@
      * <P>
      * For options that take a particular type as a parameter,
      * getOption(int) will return the parameter's value, else
-     * it will return java.lang.Boolean(false):
+     * it will return java.lang.Boolean.FALSE:
      * <PRE>
      * Object o = s.getOption(SO_LINGER);
      * if (o instanceof Integer) {
      *     System.out.print("Linger time is " + ((Integer)o).intValue());
      * } else {
-     *   // the true type of o is java.lang.Boolean(false);
+     *   // the true type of o is java.lang.Boolean.FALSE;
      * }
      * </PRE>
      *
--- a/src/java.base/share/classes/java/net/URLConnection.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/net/URLConnection.java	Thu Nov 12 14:15:05 2015 -0800
@@ -32,6 +32,7 @@
 import java.util.Hashtable;
 import java.util.Date;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.StringTokenizer;
@@ -1250,7 +1251,7 @@
 
         if (handler != null) {
             ContentHandler h = handlers.putIfAbsent(contentType, handler);
-            return h != null ? h : handler;
+            return Objects.requireNonNullElse(h, handler);
         }
 
         try {
@@ -1263,7 +1264,7 @@
         assert handler != null;
 
         ContentHandler h = handlers.putIfAbsent(contentType, handler);
-        return h != null ? h : handler;
+        return Objects.requireNonNullElse(h, handler);
     }
 
     /*
--- a/src/java.base/share/classes/java/nio/Bits.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/nio/Bits.java	Thu Nov 12 14:15:05 2015 -0800
@@ -32,7 +32,7 @@
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.VM;
 
 /**
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Nov 12 14:15:05 2015 -0800
@@ -29,7 +29,7 @@
 
 import java.io.FileDescriptor;
 import sun.misc.Cleaner;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.VM;
 import sun.nio.ch.DirectBuffer;
 
--- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Thu Nov 12 14:15:05 2015 -0800
@@ -27,7 +27,7 @@
 
 package java.nio;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
 #if[rw]
@@ -477,7 +477,7 @@
 #if[rw]
 
     public float getFloat() {
-        int x = unsafe.getIntUnaligned(hb, byteOffset(nextPutIndex(4)), bigEndian);
+        int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
         return Float.intBitsToFloat(x);
     }
 
--- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Thu Nov 12 14:15:05 2015 -0800
@@ -26,7 +26,7 @@
 package java.nio;
 
 import java.io.FileDescriptor;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 
 /**
--- a/src/java.base/share/classes/java/nio/charset/Charset.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/nio/charset/Charset.java	Thu Nov 12 14:15:05 2015 -0800
@@ -37,6 +37,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 import java.util.ServiceLoader;
 import java.util.ServiceConfigurationError;
@@ -625,6 +626,7 @@
 
     private final String name;          // tickles a bug in oldjavac
     private final String[] aliases;     // tickles a bug in oldjavac
+    private final String[] zeroAliases = new String[0];
     private Set<String> aliasSet = null;
 
     /**
@@ -642,7 +644,7 @@
      */
     protected Charset(String canonicalName, String[] aliases) {
         checkName(canonicalName);
-        String[] as = (aliases == null) ? new String[0] : aliases;
+        String[] as = Objects.requireNonNullElse(aliases, zeroAliases);
         for (int i = 0; i < as.length; i++)
             checkName(as[i]);
         this.name = canonicalName;
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Thu Nov 12 14:15:05 2015 -0800
@@ -419,7 +419,7 @@
      * @since 1.5
      */
     public String getAlgorithm() {
-        return (algorithm != null) ? algorithm : "unknown";
+        return Objects.toString(algorithm, "unknown");
     }
 
     /**
--- a/src/java.base/share/classes/java/time/ZoneId.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/time/ZoneId.java	Thu Nov 12 14:15:05 2015 -0800
@@ -310,8 +310,7 @@
     public static ZoneId of(String zoneId, Map<String, String> aliasMap) {
         Objects.requireNonNull(zoneId, "zoneId");
         Objects.requireNonNull(aliasMap, "aliasMap");
-        String id = aliasMap.get(zoneId);
-        id = (id != null ? id : zoneId);
+        String id = Objects.requireNonNullElse(aliasMap.get(zoneId), zoneId);
         return of(id);
     }
 
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java	Thu Nov 12 14:15:05 2015 -0800
@@ -177,7 +177,7 @@
     static Chronology from(TemporalAccessor temporal) {
         Objects.requireNonNull(temporal, "temporal");
         Chronology obj = temporal.query(TemporalQueries.chronology());
-        return (obj != null ? obj : IsoChronology.INSTANCE);
+        return Objects.requireNonNullElse(obj, IsoChronology.INSTANCE);
     }
 
     //-----------------------------------------------------------------------
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Thu Nov 12 14:15:05 2015 -0800
@@ -2892,7 +2892,8 @@
 
         @Override
         public String toString() {
-            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + "," + (baseDate != null ? baseDate : baseValue) + ")";
+            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth +
+                    "," + Objects.requireNonNullElse(baseDate, baseValue) + ")";
         }
     }
 
@@ -3851,6 +3852,10 @@
                     return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 } else if (context.charEquals(nextChar, 'G') && length >= position + 3 &&
                         context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) {
+                    if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) {
+                        context.setParsed(ZoneId.of("GMT0"));
+                        return position + 4;
+                    }
                     return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 }
             }
@@ -4328,7 +4333,7 @@
         private String getChronologyName(Chronology chrono, Locale locale) {
             String key = "calendarname." + chrono.getCalendarType();
             String name = DateTimeTextProvider.getLocalizedResource(key, locale);
-            return name != null ? name : chrono.getId();
+            return Objects.requireNonNullElseGet(name, () -> chrono.getId());
         }
     }
 
--- a/src/java.base/share/classes/java/time/format/DateTimePrintContext.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/time/format/DateTimePrintContext.java	Thu Nov 12 14:15:05 2015 -0800
@@ -146,7 +146,7 @@
         if (overrideZone != null) {
             // if have zone and instant, calculation is simple, defaulting chrono if necessary
             if (temporal.isSupported(INSTANT_SECONDS)) {
-                Chronology chrono = (effectiveChrono != null ? effectiveChrono : IsoChronology.INSTANCE);
+                Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE);
                 return chrono.zonedDateTime(Instant.from(temporal), overrideZone);
             }
             // block changing zone on OffsetTime, and similar problem cases
--- a/src/java.base/share/classes/java/time/temporal/IsoFields.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/time/temporal/IsoFields.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -102,7 +102,7 @@
  * The complete date is expressed using three fields:
  * <ul>
  * <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92
- * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the week within the week-based-year
+ * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4
  * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
  * </ul>
  *
@@ -571,9 +571,6 @@
         //-------------------------------------------------------------------------
         private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274};
 
-        private static boolean isIso(TemporalAccessor temporal) {
-            return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
-        }
 
         private static void ensureIso(TemporalAccessor temporal) {
             if (isIso(temporal) == false) {
@@ -681,7 +678,7 @@
 
         @Override
         public boolean isSupportedBy(Temporal temporal) {
-            return temporal.isSupported(EPOCH_DAY);
+            return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
         }
 
         @SuppressWarnings("unchecked")
@@ -721,4 +718,8 @@
             return name;
         }
     }
+
+    static boolean isIso(TemporalAccessor temporal) {
+        return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
+    }
 }
--- a/src/java.base/share/classes/java/util/Arrays.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/Arrays.java	Thu Nov 12 14:15:05 2015 -0800
@@ -2882,6 +2882,7 @@
      * @param a2 the other array to be tested for equality
      * @return {@code true} if the two arrays are equal
      */
+    @HotSpotIntrinsicCandidate
     public static boolean equals(byte[] a, byte[] a2) {
         if (a==a2)
             return true;
--- a/src/java.base/share/classes/java/util/Collections.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/Collections.java	Thu Nov 12 14:15:05 2015 -0800
@@ -2090,7 +2090,8 @@
      * through the returned set.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * set when iterating over it:
+     * collection when traversing it via {@link Iterator}, {@link Spliterator}
+     * or {@link Stream}:
      * <pre>
      *  Set s = Collections.synchronizedSet(new HashSet());
      *      ...
@@ -2149,8 +2150,9 @@
      * through the returned sorted set (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * sorted set when iterating over it or any of its {@code subSet},
-     * {@code headSet}, or {@code tailSet} views.
+     * sorted set when traversing it or any of its {@code subSet},
+     * {@code headSet}, or {@code tailSet} views via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
      *      ...
@@ -2240,8 +2242,9 @@
      * accomplished through the returned navigable set (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * navigable set when iterating over it or any of its {@code subSet},
-     * {@code headSet}, or {@code tailSet} views.
+     * navigable set when traversing it, or any of its {@code subSet},
+     * {@code headSet}, or {@code tailSet} views, via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
      *      ...
@@ -2355,7 +2358,8 @@
      * through the returned list.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * list when iterating over it:
+     * list when traversing it via {@link Iterator}, {@link Spliterator}
+     * or {@link Stream}:
      * <pre>
      *  List list = Collections.synchronizedList(new ArrayList());
      *      ...
@@ -2523,7 +2527,8 @@
      * through the returned map.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * map when iterating over any of its collection views:
+     * map when traversing any of its collection views via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  Map m = Collections.synchronizedMap(new HashMap());
      *      ...
@@ -2700,9 +2705,10 @@
      * through the returned sorted map (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * sorted map when iterating over any of its collection views, or the
+     * sorted map when traversing any of its collection views, or the
      * collections views of any of its {@code subMap}, {@code headMap} or
-     * {@code tailMap} views.
+     * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
+     * {@link Stream}:
      * <pre>
      *  SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
      *      ...
@@ -2797,9 +2803,10 @@
      * accomplished through the returned navigable map (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * navigable map when iterating over any of its collection views, or the
+     * navigable map when traversing any of its collection views, or the
      * collections views of any of its {@code subMap}, {@code headMap} or
-     * {@code tailMap} views.
+     * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
+     * {@link Stream}:
      * <pre>
      *  NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
      *      ...
--- a/src/java.base/share/classes/java/util/Formatter.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/Formatter.java	Thu Nov 12 14:15:05 2015 -0800
@@ -49,6 +49,7 @@
 import java.text.NumberFormat;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.Objects;
 
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -3860,7 +3861,7 @@
                     ampm = dfs.getAmPmStrings();
                 }
                 String s = ampm[t.get(Calendar.AM_PM)];
-                sb.append(s.toLowerCase(l != null ? l : Locale.US));
+                sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
             case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@@ -3893,7 +3894,7 @@
                 TimeZone tz = t.getTimeZone();
                 sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0),
                                            TimeZone.SHORT,
-                                            (l == null) ? Locale.US : l));
+                                           Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
 
@@ -3901,7 +3902,7 @@
             case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
             case DateTime.NAME_OF_DAY:          { // 'A'
                 int i = t.get(Calendar.DAY_OF_WEEK);
-                Locale lt = ((l == null) ? Locale.US : l);
+                Locale lt = Objects.requireNonNullElse(l, Locale.US);
                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                 if (c == DateTime.NAME_OF_DAY)
                     sb.append(dfs.getWeekdays()[i]);
@@ -3913,7 +3914,7 @@
             case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
             case DateTime.NAME_OF_MONTH:        { // 'B'
                 int i = t.get(Calendar.MONTH);
-                Locale lt = ((l == null) ? Locale.US : l);
+                Locale lt = Objects.requireNonNullElse(l, Locale.US);
                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                 if (c == DateTime.NAME_OF_MONTH)
                     sb.append(dfs.getMonths()[i]);
@@ -3984,7 +3985,7 @@
                 StringBuilder tsb = new StringBuilder();
                 print(tsb, t, DateTime.AM_PM, l);
 
-                sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
+                sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
             case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
@@ -4092,7 +4093,7 @@
                         ampm = dfs.getAmPmStrings();
                     }
                     String s = ampm[t.get(ChronoField.AMPM_OF_DAY)];
-                    sb.append(s.toLowerCase(l != null ? l : Locale.US));
+                    sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
                     break;
                 }
                 case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@@ -4131,7 +4132,7 @@
                         sb.append(TimeZone.getTimeZone(zid.getId())
                                           .getDisplayName(zid.getRules().isDaylightSavings(instant),
                                                           TimeZone.SHORT,
-                                                          (l == null) ? Locale.US : l));
+                                                          Objects.requireNonNullElse(l, Locale.US)));
                         break;
                     }
                     sb.append(zid.getId());
@@ -4141,7 +4142,7 @@
                 case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
                 case DateTime.NAME_OF_DAY:          { // 'A'
                     int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1;
-                    Locale lt = ((l == null) ? Locale.US : l);
+                    Locale lt = Objects.requireNonNullElse(l, Locale.US);
                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                     if (c == DateTime.NAME_OF_DAY)
                         sb.append(dfs.getWeekdays()[i]);
@@ -4153,7 +4154,7 @@
                 case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
                 case DateTime.NAME_OF_MONTH:        { // 'B'
                     int i = t.get(ChronoField.MONTH_OF_YEAR) - 1;
-                    Locale lt = ((l == null) ? Locale.US : l);
+                    Locale lt = Objects.requireNonNullElse(l, Locale.US);
                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                     if (c == DateTime.NAME_OF_MONTH)
                         sb.append(dfs.getMonths()[i]);
@@ -4223,7 +4224,7 @@
                     // this may be in wrong place for some locales
                     StringBuilder tsb = new StringBuilder();
                     print(tsb, t, DateTime.AM_PM, l);
-                    sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
+                    sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
                     break;
                 }
                 case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
--- a/src/java.base/share/classes/java/util/Objects.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/Objects.java	Thu Nov 12 14:15:05 2015 -0800
@@ -295,7 +295,7 @@
      *        {@code defaultObj} is {@code null}
      * @since 9
      */
-    public static <T> T nonNullElse(T obj, T defaultObj) {
+    public static <T> T requireNonNullElse(T obj, T defaultObj) {
         return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
     }
 
@@ -314,8 +314,9 @@
      *        the {@code supplier.get()} value is {@code null}
      * @since 9
      */
-    public static <T> T nonNullElseGet(T obj, Supplier<? extends T> supplier) {
-        return (obj != null) ? obj : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
+    public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
+        return (obj != null) ? obj
+                : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
     }
 
     /**
--- a/src/java.base/share/classes/java/util/Random.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/Random.java	Thu Nov 12 14:15:05 2015 -0800
@@ -34,7 +34,7 @@
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * An instance of this class is used to generate a stream of
--- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Thu Nov 12 14:15:05 2015 -0800
@@ -2775,7 +2775,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long RESULT;
     private static final long STACK;
     private static final long NEXT;
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Nov 12 14:15:05 2015 -0800
@@ -297,7 +297,7 @@
      * Table accesses require volatile/atomic reads, writes, and
      * CASes.  Because there is no other way to arrange this without
      * adding further indirections, we use intrinsics
-     * (sun.misc.Unsafe) operations.
+     * (jdk.internal.misc.Unsafe) operations.
      *
      * We use the top (sign) bit of Node hash fields for control
      * purposes -- it is available anyway because of addressing
@@ -3287,7 +3287,7 @@
             return true;
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long LOCKSTATE;
         static {
             try {
@@ -6330,7 +6330,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Thu Nov 12 14:15:05 2015 -0800
@@ -326,7 +326,7 @@
 
         // Unsafe mechanics
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long PREV;
         private static final long ITEM;
         private static final long NEXT;
@@ -1608,7 +1608,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     static {
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Nov 12 14:15:05 2015 -0800
@@ -929,7 +929,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     private static final long ITEM;
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Nov 12 14:15:05 2015 -0800
@@ -534,7 +534,7 @@
 
         // Unsafe mechanics
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long VALUE;
         private static final long NEXT;
 
@@ -614,7 +614,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long RIGHT;
         static {
             try {
@@ -3596,7 +3596,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Thu Nov 12 14:15:05 2015 -0800
@@ -510,7 +510,7 @@
         U.putObjectVolatile(this, MAP, map);
     }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long MAP;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1545,7 +1545,7 @@
     private void resetLock() {
         U.putObjectVolatile(this, LOCK, new Object());
     }
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long LOCK;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Thu Nov 12 14:15:05 2015 -0800
@@ -754,7 +754,7 @@
     protected void setRawResult(T t) { }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PENDING;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Thu Nov 12 14:15:05 2015 -0800
@@ -625,7 +625,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long BOUND;
     private static final long SLOT;
     private static final long MATCH;
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1337,7 +1337,7 @@
         }
 
         // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long QLOCK;
         private static final int ABASE;
         private static final int ASHIFT;
@@ -3452,7 +3452,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long CTL;
     private static final long RUNSTATE;
     private static final int ABASE;
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1517,7 +1517,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATUS;
 
     static {
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Nov 12 14:15:05 2015 -0800
@@ -185,7 +185,7 @@
     }
 
     // Set up to allow setting thread fields in constructor
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long THREADLOCALS;
     private static final long INHERITABLETHREADLOCALS;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
@@ -248,7 +248,7 @@
          */
         private static ThreadGroup createThreadGroup() {
             try {
-                sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
+                jdk.internal.misc.Unsafe u = jdk.internal.misc.Unsafe.getUnsafe();
                 long tg = u.objectFieldOffset
                     (Thread.class.getDeclaredField("group"));
                 long gp = u.objectFieldOffset
--- a/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Thu Nov 12 14:15:05 2015 -0800
@@ -484,7 +484,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long RUNNER;
     private static final long WAITERS;
--- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Thu Nov 12 14:15:05 2015 -0800
@@ -538,7 +538,7 @@
         private static final long serialVersionUID = -3375979862319811754L;
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long ITEM;
         private static final long NEXT;
         private static final long WAITER;
@@ -1564,7 +1564,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     private static final long SWEEPVOTES;
--- a/src/java.base/share/classes/java/util/concurrent/Phaser.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/Phaser.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1137,7 +1137,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1010,7 +1010,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long ALLOCATIONSPINLOCK;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1596,7 +1596,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long CTL;
         private static final long TAIL;
         private static final long HEAD;
--- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Thu Nov 12 14:15:05 2015 -0800
@@ -283,7 +283,7 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
             private static final long MATCH;
             private static final long NEXT;
 
@@ -509,7 +509,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long HEAD;
         static {
             try {
@@ -575,7 +575,7 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
             private static final long ITEM;
             private static final long NEXT;
 
@@ -817,7 +817,7 @@
             }
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long HEAD;
         private static final long TAIL;
         private static final long CLEANME;
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1050,7 +1050,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long SEED;
     private static final long PROBE;
     private static final long SECONDARY;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Thu Nov 12 14:15:05 2015 -0800
@@ -49,7 +49,7 @@
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Thu Nov 12 14:15:05 2015 -0800
@@ -54,7 +54,7 @@
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Thu Nov 12 14:15:05 2015 -0800
@@ -49,7 +49,7 @@
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final int ABASE;
     private static final int ASHIFT;
     private final int[] array;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Nov 12 14:15:05 2015 -0800
@@ -367,7 +367,7 @@
      */
     private static class AtomicIntegerFieldUpdaterImpl<T>
             extends AtomicIntegerFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Thu Nov 12 14:15:05 2015 -0800
@@ -54,7 +54,7 @@
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Thu Nov 12 14:15:05 2015 -0800
@@ -48,7 +48,7 @@
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final int ABASE;
     private static final int ASHIFT;
     private final long[] array;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Nov 12 14:15:05 2015 -0800
@@ -366,7 +366,7 @@
     }
 
     private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
@@ -490,7 +490,7 @@
 
 
     private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Thu Nov 12 14:15:05 2015 -0800
@@ -190,7 +190,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PAIR;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Thu Nov 12 14:15:05 2015 -0800
@@ -49,7 +49,7 @@
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Thu Nov 12 14:15:05 2015 -0800
@@ -52,7 +52,7 @@
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long ARRAY;
     private static final int ABASE;
     private static final int ASHIFT;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Nov 12 14:15:05 2015 -0800
@@ -284,7 +284,7 @@
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<V> vclass;
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Thu Nov 12 14:15:05 2015 -0800
@@ -190,7 +190,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PAIR;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Thu Nov 12 14:15:05 2015 -0800
@@ -133,7 +133,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long VALUE;
         static {
             try {
@@ -372,7 +372,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long BASE;
     private static final long CELLSBUSY;
     private static final long PROBE;
--- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1821,7 +1821,7 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long HEAD;
     private static final long TAIL;
--- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Thu Nov 12 14:15:05 2015 -0800
@@ -524,7 +524,7 @@
             return U.compareAndSwapObject(this, NEXT, expect, update);
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long NEXT;
         static final long PREV;
         private static final long THREAD;
@@ -2285,7 +2285,7 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long HEAD;
     private static final long TAIL;
--- a/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Thu Nov 12 14:15:05 2015 -0800
@@ -394,7 +394,7 @@
     }
 
     // Hotspot implementation via intrinsics API
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PARKBLOCKER;
     private static final long SECONDARY;
     static {
--- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1501,7 +1501,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long TID;
     static {
         try {
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Thu Nov 12 14:15:05 2015 -0800
@@ -1398,7 +1398,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long WHEAD;
     private static final long WTAIL;
--- a/src/java.base/share/classes/java/util/zip/CRC32C.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/java/util/zip/CRC32C.java	Thu Nov 12 14:15:05 2015 -0800
@@ -28,7 +28,7 @@
 import java.nio.ByteOrder;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.nio.ch.DirectBuffer;
 
 /**
--- a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Thu Nov 12 10:39:06 2015 -0800
+++ b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Thu Nov 12 14:15:05 2015 -0800
@@ -30,7 +30,7 @@
 import java.io.FileDescriptor;
 import java.security.ProtectionDomain;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /** A repository of "shared secrets", which are a mechanism for
     calling implementation-private methods in another package without
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Nov 12 14:15:05 2015 -0800
@@ -0,0 +1,1391 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.lang.reflect.Field;
+import java.security.ProtectionDomain;
+
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+import sun.misc.VM;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+
+/**
+ * A collection of methods for performing low-level, unsafe operations.
+ * Although the class and all methods are public, use of this class is
+ * limited because only trusted code can obtain instances of it.
+ *
+ * @author John R. Rose
+ * @see #getUnsafe
+ */
+
+public final class Unsafe {
+
+    private static native void registerNatives();
+    static {
+        registerNatives();
+        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
+    }
+
+    private Unsafe() {}
+
+    private static final Unsafe theUnsafe = new Unsafe();
+
+    /**
+     * Provides the caller with the capability of performing unsafe
+     * operations.
+     *
+     * <p>The returned {@code Unsafe} object should be carefully guarded
+     * by the caller, since it can be used to read and write data at arbitrary
+     * memory addresses.  It must never be passed to untrusted code.
+     *
+     * <p>Most methods in this class are very low-level, and correspond to a
+     * small number of hardware instructions (on typical machines).  Compilers
+     * are encouraged to optimize these methods accordingly.
+     *
+     * <p>Here is a suggested idiom for using unsafe operations:
+     *
+     * <pre> {@code
+     * class MyTrustedClass {
+     *   private static final Unsafe unsafe = Unsafe.getUnsafe();
+     *   ...
+     *   private long myCountAddress = ...;
+     *   public int getCount() { return unsafe.getByte(myCountAddress); }
+     * }}</pre>
+     *
+     * (It may assist compilers to make the local variable {@code final}.)
+     *
+     * @throws  SecurityException  if a security manager exists and its
+     *          {@code checkPropertiesAccess} method doesn't allow
+     *