changeset 5265:aa49fe749096 jdk7u6-b13

Merge
author lana
date Fri, 01 Jun 2012 11:46:14 -0700
parents 41d19a05e821 3335ab17d926
children 96a023de3ddf
files
diffstat 65 files changed, 2624 insertions(+), 644 deletions(-) [+]
line wrap: on
line diff
--- a/make/bridge/Jabswitch/Makefile	Thu May 31 14:06:48 2012 -0700
+++ b/make/bridge/Jabswitch/Makefile	Fri Jun 01 11:46:14 2012 -0700
@@ -35,6 +35,7 @@
 CPLUSPLUSLIBRARY=true
 
 VERSIONINFO_RESOURCE = $(CLOSED_PLATFORM_SRC)/native/sun/bridge/AccessBridgeStatusWindow.rc
+VERSIONRES = $(TEMPDIR)/AccessBridgeStatusWindow.res
 
 JAB_EXE= $(TEMPDIR)/jabswitch.exe
 
@@ -43,15 +44,16 @@
 JAB_MANIFEST_INP = $(CLOSED_PLATFORM_SRC)/native/sun/bridge/jabswitch.manifest
 JAB_MANIFEST_OUT = $(TEMPDIR)/jabswitch.exe.intermediate.manifest
 
-RC_FLAGS += -d "JAB_MANIFEST_EMBED=$(JAB_MANIFEST_EMBED)" 
-OTHER_CPPFLAGS += /Fo"$(TEMPDIR)/" /Fd"$(TEMPDIR)/" 
-LDDFLAGS +=/manifest /ManifestFile:$(JAB_MANIFEST_INP) /MANIFESTUAC:"level='requireAdministrator' uiAccess='false'" 
+RC_FLAGS += /fo "$(VERSIONRES)"
+OTHER_CPPFLAGS += /Fo"$(TEMPDIR)/" /Fd"$(TEMPDIR)/" /analyze- /Od /Gd /nologo /MDd /Gm /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /RTC1 /W3 /ZI /Zc:wchar_t /EHsc 
+LDDFLAGS += Advapi32.lib Version.lib User32.lib
 
 all: buildexe copyfilejab
 
 buildexe : 
 	$(CD) $(TEMPDIR)  
-	$(CC) $(CPPFLAGS) $(JAB_SRC) $(LDDFLAGS) -o $(JAB_EXE) 
+	$(RC) $(RC_FLAGS) $(VERSIONINFO_RESOURCE) 
+	$(CC) $(CPPFLAGS) $(JAB_SRC) $(LDDFLAGS) $(VERSIONRES) -o $(JAB_EXE) 
 	$(MT) /nologo /verbose /manifest $(JAB_MANIFEST_INP) /outputresource:$(JAB_EXE)  
 
 copyfilejab : 
--- a/make/common/Defs-solaris.gmk	Thu May 31 14:06:48 2012 -0700
+++ b/make/common/Defs-solaris.gmk	Fri Jun 01 11:46:14 2012 -0700
@@ -100,6 +100,9 @@
 # variable names because the incoming option value can be overridden
 # in some situations, e.g., a VARIANT != OPT build.
 
+ADD_GNU_DEBUGLINK = $(ABS_BUILDTOOLBINDIR)/add_gnu_debuglink
+FIX_EMPTY_SEC_HDR_FLAGS = $(ABS_BUILDTOOLBINDIR)/fix_empty_sec_hdr_flags
+
 ifeq ($(VARIANT), OPT)
   FULL_DEBUG_SYMBOLS ?= 1
   ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
@@ -114,26 +117,11 @@
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   # Default OBJCOPY comes from the SUNWbinutils package:
   DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
-  ifeq ($(PLATFORM)-$(LIBARCH), solaris-amd64)
-    # On Solaris AMD64/X64, gobjcopy is not happy and fails:
-    #
-    # usr/sfw/bin/gobjcopy --add-gnu-debuglink=<lib>.debuginfo <lib>.so
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: libsaproc.debuginfo: Bad value
-    # BFD: stKPaiop: Not enough room for program headers, try linking with -N
-    # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value
-    _JUNK_ := $(shell \
-      echo >&2 "INFO: $(DEF_OBJCOPY) is not working on Solaris AMD64/X64")
-    OBJCOPY=
-  else
-    OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
-    ifneq ($(ALT_OBJCOPY),)
-      _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
-      # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
-      OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
-    endif
+  OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
+  ifneq ($(ALT_OBJCOPY),)
+    _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
+    # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path
+    OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
   endif
 
   # Setting ENABLE_FULL_DEBUG_SYMBOLS=1 (and OBJCOPY) above enables the
--- a/make/common/Defs.gmk	Thu May 31 14:06:48 2012 -0700
+++ b/make/common/Defs.gmk	Fri Jun 01 11:46:14 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -281,6 +281,7 @@
 ABS_BUILDTOOLJARDIR = $(ABS_OUTPUTDIR)/btjars
 # for generated tool class files
 BUILDTOOLBINDIR     = $(OUTPUTDIR)/btbins
+ABS_BUILDTOOLBINDIR = $(ABS_OUTPUTDIR)/btbins
 # for generated java source files
 GENSRCDIR           = $(OUTPUTDIR)/gensrc
 # for generated C source files (not javah)
--- a/make/common/Library.gmk	Thu May 31 14:06:48 2012 -0700
+++ b/make/common/Library.gmk	Fri Jun 01 11:46:14 2012 -0700
@@ -248,6 +248,12 @@
   ARFLAGS = -r
 endif
 
+ifeq ($(PLATFORM), solaris)
+  ifeq ($(LIBRARY_SUPPORTS_FULL_DEBUG_SYMBOLS),1)
+$(ACTUAL_LIBRARY):: $(ADD_GNU_DEBUGLINK) $(FIX_EMPTY_SEC_HDR_FLAGS)
+  endif
+endif
+
 $(ACTUAL_LIBRARY):: $(COMPILE_FILES_o) $(FILES_m) $(FILES_reorder)
 	@$(prep-target)
 	@$(ECHO) "STATS: LIBRARY=$(LIBRARY), PRODUCT=$(PRODUCT), OPTIMIZATION_LEVEL=$(OPTIMIZATION_LEVEL)"
@@ -263,11 +269,29 @@
   ifneq ($(PLATFORM), macosx)
     ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
       ifeq ($(LIBRARY_SUPPORTS_FULL_DEBUG_SYMBOLS),1)
+        ifeq ($(PLATFORM), solaris)
+# gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
+# Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
+# empty section headers until a fixed $(OBJCOPY) is available.
+# An empty section header has sh_addr == 0 and sh_size == 0.
+# This problem has only been seen on Solaris X64, but we call this tool
+# on all Solaris builds just in case.
+#
+# $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
+# Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
 	(set -e ; \
 	 $(CD) $(@D) ; \
-	 $(OBJCOPY) --only-keep-debug $(@F) $(LIBRARY).debuginfo ; \
-	 $(OBJCOPY) --add-gnu-debuglink=$(LIBRARY).debuginfo $(@F) ; \
+	 $(FIX_EMPTY_SEC_HDR_FLAGS) $(@F) ; \
+	 $(OBJCOPY) --only-keep-debug $(@F) $(LIB_PREFIX)$(LIBRARY).debuginfo ; \
+         $(ADD_GNU_DEBUGLINK) $(LIB_PREFIX)$(LIBRARY).debuginfo $(@F) ; \
 	)
+        else # PLATFORM != solaris
+	(set -e ; \
+	 $(CD) $(@D) ; \
+	 $(OBJCOPY) --only-keep-debug $(@F) $(LIB_PREFIX)$(LIBRARY).debuginfo ; \
+	 $(OBJCOPY) --add-gnu-debuglink=$(LIB_PREFIX)$(LIBRARY).debuginfo $(@F) ; \
+	)
+        endif # PLATFORM == solaris
         ifeq ($(STRIP_POLICY),all_strip)
 	  $(STRIP) $@
         else
@@ -284,8 +308,8 @@
         ifeq ($(ZIP_DEBUGINFO_FILES),1)
 	  (set -e ; \
 	   $(CD) $(@D) ; \
-	   $(ZIPEXE) -q $(LIBRARY).diz $(LIBRARY).debuginfo ; \
-	   $(RM) $(LIBRARY).debuginfo ; \
+	   $(ZIPEXE) -q $(LIB_PREFIX)$(LIBRARY).diz $(LIB_PREFIX)$(LIBRARY).debuginfo ; \
+	   $(RM) $(LIB_PREFIX)$(LIBRARY).debuginfo ; \
 	  )
         endif
       endif # LIBRARY_SUPPORTS_FULL_DEBUG_SYMBOLS
--- a/make/common/Program.gmk	Thu May 31 14:06:48 2012 -0700
+++ b/make/common/Program.gmk	Fri Jun 01 11:46:14 2012 -0700
@@ -230,6 +230,13 @@
   #
   # This rule only applies on unix.  It supports quantify and its ilk.
   #
+
+  ifeq ($(PLATFORM), solaris)
+    ifeq ($(PROGRAM_SUPPORTS_FULL_DEBUG_SYMBOLS),1)
+  $(ACTUAL_PROGRAM):: $(ADD_GNU_DEBUGLINK) $(FIX_EMPTY_SEC_HDR_FLAGS)
+    endif
+  endif
+
   $(ACTUAL_PROGRAM):: $(FILES_o)
 	@$(prep-target)
 	@set -- $?; \
@@ -244,11 +251,29 @@
   ifneq ($(PLATFORM), macosx)
     ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
       ifeq ($(PROGRAM_SUPPORTS_FULL_DEBUG_SYMBOLS),1)
+        ifeq ($(PLATFORM), solaris)
+# gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
+# Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
+# empty section headers until a fixed $(OBJCOPY) is available.
+# An empty section header has sh_addr == 0 and sh_size == 0.
+# This problem has only been seen on Solaris X64, but we call this tool
+# on all Solaris builds just in case.
+#
+# $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
+# Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
+	(set -e ; \
+	 $(CD) $(@D) ; \
+	 $(FIX_EMPTY_SEC_HDR_FLAGS) $(@F) ; \
+	 $(OBJCOPY) --only-keep-debug $(@F) $(@F).debuginfo ; \
+         $(ADD_GNU_DEBUGLINK) $(@F).debuginfo $(@F) ; \
+	)
+        else # PLATFORM != solaris
 	(set -e ; \
 	 $(CD) $(@D) ; \
 	 $(OBJCOPY) --only-keep-debug $(@F) $(@F).debuginfo ; \
 	 $(OBJCOPY) --add-gnu-debuglink=$(@F).debuginfo $(@F) ; \
 	)
+        endif # PLATFORM == solaris
         ifeq ($(STRIP_POLICY),all_strip)
 	  $(STRIP) $@
         else
--- a/make/java/java/FILES_java.gmk	Thu May 31 14:06:48 2012 -0700
+++ b/make/java/java/FILES_java.gmk	Fri Jun 01 11:46:14 2012 -0700
@@ -482,6 +482,7 @@
     sun/misc/JavaNioAccess.java \
     sun/misc/Perf.java \
     sun/misc/PerfCounter.java \
+    sun/misc/Hashing.java \
     sun/net/www/protocol/jar/Handler.java \
     sun/net/www/protocol/jar/JarURLConnection.java \
     sun/net/www/protocol/file/Handler.java \
--- a/make/sun/xawt/Makefile	Thu May 31 14:06:48 2012 -0700
+++ b/make/sun/xawt/Makefile	Fri Jun 01 11:46:14 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -232,10 +232,16 @@
 SIZERS = $(SIZER).32
 SIZERS_C = $(SIZER_32_C)
 SIZES = $(WRAPPER_GENERATOR_DIR)/sizes.32
+ifdef CROSS_COMPILE_ARCH
+CFLAGS_32 = -m32
+endif
 else # !32
 SIZERS = $(SIZER).64
 SIZERS_C = $(SIZER_64_C)
 SIZES = $(WRAPPER_GENERATOR_DIR)/sizes.64
+ifdef CROSS_COMPILE_ARCH
+CFLAGS_64 = -m64
+endif
 endif # 32
 endif # !macosx
 endif # solaris
@@ -271,13 +277,15 @@
 WRAPPER_GENERATOR_CLASS=$(WRAPPER_GENERATOR_TEMPDIR)/WrapperGenerator.class 
 XLIBTYPES=$(PLATFORM_SRC)/classes/sun/awt/X11/generator/xlibtypes.txt
 
+ifndef CROSS_COMPILE_ARCH
+SIZERS_CC = $(CC)
+else
+SIZERS_CC = $(HOST_CC)
+endif
+
 $(SIZERS): $(SIZERS_C) 
 	$(prep-target)
-ifndef CROSS_COMPILE_ARCH
-	$(CC) $(CFLAGS_$(subst .,,$(suffix $@))) $(CPPFLAGS) -o $@ $(SIZER)$(suffix $@).c
-else
-	$(HOST_CC) $(CPPFLAGS) -o $@ $(SIZER)$(suffix $@).c
-endif
+	$(SIZERS_CC) $(CFLAGS_$(subst .,,$(suffix $@))) $(CPPFLAGS) -o $@ $(SIZER)$(suffix $@).c
 
 $(WRAPPER_GENERATOR_CLASS): $(WRAPPER_GENERATOR_JAVA)
 	$(prep-target)
--- a/make/tools/Makefile	Thu May 31 14:06:48 2012 -0700
+++ b/make/tools/Makefile	Fri Jun 01 11:46:14 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -56,6 +56,11 @@
   SUBDIRS += generate_nimbus
 endif
 
+ifeq ($(PLATFORM), solaris)
+  # temporary tools to work around gobjcopy bugs
+  SUBDIRS += add_gnu_debuglink fix_empty_sec_hdr_flags
+endif
+
 include $(BUILDDIR)/common/Subdirs.gmk
 
 all build clean clobber::
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/add_gnu_debuglink/Makefile	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#  
+#
+
+# Rules to build add_gnu_debuglink, used by various Makefiles on Solaris
+
+BUILDDIR = ../..
+include $(BUILDDIR)/common/Defs.gmk
+
+# Default name
+PROGRAM = add_gnu_debuglink
+ADD_GNU_DEBUGLINK_PROG = $(ABS_BUILDTOOLBINDIR)/$(PROGRAM)
+
+ADD_GNU_DEBUGLINK_SRC     = add_gnu_debuglink.c
+ADD_GNU_DEBUGLINK_FLAGS   = 
+LIBS_ADD_GNU_DEBUGLINK   += -lelf
+
+all: $(ADD_GNU_DEBUGLINK)
+
+$(ADD_GNU_DEBUGLINK_PROG): $(ADD_GNU_DEBUGLINK_SRC)
+	$(MKDIR) -p $(BUILDTOOLBINDIR)
+	$(CC) -g -o $@ $< $(ADD_GNU_DEBUGLINK_FLAGS) $(LIBS_ADD_GNU_DEBUGLINK)
+
+clean::
+	$(RM) $(ADD_GNU_DEBUGLINK_PROG)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/add_gnu_debuglink/add_gnu_debuglink.c	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Name:        add_gnu_debuglink.c
+ *
+ * Description: Add a ".gnu_debuglink" section that refers to the specified
+ *     debug_info_path to the specified ELF object.
+ *
+ *     This program is adapted from the example program shown on the
+ *     elf(3elf) man page and from code from the Solaris compiler
+ *     driver.
+ */
+
+/*
+ * needed to define SHF_EXCLUDE
+ */
+#define ELF_TARGET_ALL
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void failure(void);
+static unsigned int gnu_debuglink_crc32(unsigned int crc, unsigned char *buf,
+                                        size_t len);
+
+void
+main(int argc, char ** argv) {
+                                 /* new ELF section name */
+    static char SEC_NAME[] = ".gnu_debuglink";
+
+    unsigned char buffer[8 * 1024];  /* I/O buffer */
+    int           buffer_len;        /* buffer length */
+    char *        debug_info_path;   /* debug info path */
+    void *        ehdr;              /* ELF header */
+    Elf *         elf;               /* ELF descriptor */
+    char *        elf_ident;         /* ELF identity string */
+    char *        elf_obj;           /* elf_obj file */
+    int           fd;                /* descriptor for files */
+    unsigned int  file_crc = 0;      /* CRC for debug info file */
+    int           is_elfclass64;     /* is an ELFCLASS64 file? */
+    Elf_Data *    link_dat;          /* ELF data for new debug info link */
+    Elf_Data *    name_dat;          /* ELF data for new section name */
+    Elf_Scn *     new_scn;           /* new ELF section descriptor */
+    void *        new_shdr;          /* new ELF section header */
+    Elf_Scn *     scn;               /* ELF section descriptor */
+    void *        shdr;              /* ELF section header */
+
+    if (argc != 3) {
+        (void) fprintf(stderr, "Usage: %s debug_info_path elf_obj\n", argv[0]);
+        exit(2);
+    }
+
+    debug_info_path = argv[1];  /* save for later */
+    if ((fd = open(debug_info_path, O_RDONLY)) == -1) {
+        (void) fprintf(stderr, "%s: cannot open file.\n", debug_info_path);
+        exit(3);
+    }
+
+    (void) printf("Computing CRC for '%s'\n", debug_info_path);
+    (void) fflush(stdout);
+    /* compute CRC for the debug info file */
+    for (;;) {
+        int len = read(fd, buffer, sizeof buffer);
+        if (len <= 0) {
+            break;
+        }
+        file_crc = gnu_debuglink_crc32(file_crc, buffer, len);
+    }
+    (void) close(fd);
+
+    /* open the elf_obj */
+    elf_obj = argv[2];
+    if ((fd = open(elf_obj, O_RDWR)) == -1) {
+        (void) fprintf(stderr, "%s: cannot open file.\n", elf_obj);
+        exit(4);
+    }
+
+    (void) printf("Opening '%s' for update\n", elf_obj);
+    (void) fflush(stdout);
+    (void) elf_version(EV_CURRENT);  /* coordinate ELF versions */
+
+    /* obtain the ELF descriptors from the input file */
+    if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
+        failure();
+    }
+
+    /* determine if ELFCLASS64 or not? */
+    elf_ident = elf_getident(elf, NULL);
+    is_elfclass64 = (elf_ident[EI_CLASS] == ELFCLASS64);
+
+    /* get the ELF header */
+    if (is_elfclass64) {
+        ehdr = elf64_getehdr(elf);
+    } else {
+        ehdr = elf32_getehdr(elf);
+    }
+    if (ehdr == NULL) {
+        failure();
+    }
+
+    /* get the ELF section descriptor */
+    if (is_elfclass64) {
+        scn = elf_getscn(elf, ((Elf64_Ehdr *) ehdr)->e_shstrndx);
+    } else {
+        scn = elf_getscn(elf, ((Elf32_Ehdr *) ehdr)->e_shstrndx);
+    }
+    if (scn == NULL) {
+        failure();
+    }
+
+    /* get the section header */
+    if (is_elfclass64) {
+        shdr = elf64_getshdr(scn);
+    } else {
+        shdr = elf32_getshdr(scn);
+    }
+    if (shdr == NULL) {
+        failure();
+    }
+
+    (void) printf("Adding ELF data for new section name\n");
+    (void) fflush(stdout);
+    name_dat = elf_newdata(scn);
+    name_dat->d_buf = (void *) SEC_NAME;
+    if (is_elfclass64) {
+        name_dat->d_off = ((Elf64_Shdr *) shdr)->sh_size + 1;
+    } else {
+        name_dat->d_off = ((Elf32_Shdr *) shdr)->sh_size + 1;
+    }
+    name_dat->d_align = 1;
+    name_dat->d_size = strlen(SEC_NAME) + 1;
+
+    new_scn = elf_newscn(elf);
+
+    if (is_elfclass64) {
+        new_shdr = elf64_getshdr(new_scn);
+        ((Elf64_Shdr *) new_shdr)->sh_flags = SHF_EXCLUDE;
+        ((Elf64_Shdr *) new_shdr)->sh_type = SHT_PROGBITS;
+        ((Elf64_Shdr *) new_shdr)->sh_name = ((Elf64_Shdr *) shdr)->sh_size;
+        ((Elf64_Shdr *) new_shdr)->sh_addralign = 1;
+        ((Elf64_Shdr *) shdr)->sh_size += (strlen(SEC_NAME) + 1);
+    } else {
+        new_shdr = elf32_getshdr(new_scn);
+        ((Elf32_Shdr *) new_shdr)->sh_flags = SHF_EXCLUDE;
+        ((Elf32_Shdr *) new_shdr)->sh_type = SHT_PROGBITS;
+        ((Elf32_Shdr *) new_shdr)->sh_name = ((Elf32_Shdr *) shdr)->sh_size;
+        ((Elf32_Shdr *) new_shdr)->sh_addralign = 1;
+        ((Elf32_Shdr *) shdr)->sh_size += (strlen(SEC_NAME) + 1);
+    }
+
+    (void) printf("Adding ELF data for debug_info_path value\n");
+    (void) fflush(stdout);
+    (void) memset(buffer, 0, sizeof buffer);
+    buffer_len = strlen(debug_info_path) + 1;  /* +1 for NUL */
+    (void) strncpy((char *) buffer, debug_info_path, buffer_len);
+    if (buffer_len % 4 != 0) {
+        /* not on a 4 byte boundary so pad to the next one */
+        buffer_len += (4 - buffer_len % 4);
+    }
+    /* save the CRC */
+    (void) memcpy(&buffer[buffer_len], &file_crc, sizeof file_crc);
+    buffer_len += sizeof file_crc;
+
+    link_dat = elf_newdata(new_scn);
+    link_dat->d_type = ELF_T_BYTE;
+    link_dat->d_size = buffer_len;
+    link_dat->d_buf = buffer;
+    link_dat->d_align = 1;
+
+    (void) printf("Saving updates to '%s'\n", elf_obj);
+    (void) fflush(stdout);
+    (void) elf_update(elf, ELF_C_NULL);   /* recalc ELF memory structures */
+    (void) elf_update(elf, ELF_C_WRITE);  /* write out changes to ELF obj */
+    (void) elf_end(elf);                  /* done with ELF obj */
+    (void) close(fd);
+
+    (void) printf("Done updating '%s'\n", elf_obj);
+    (void) fflush(stdout);
+    exit(0);
+}  /* end main */
+
+
+static void
+failure() {
+    (void) fprintf(stderr, "%s\n", elf_errmsg(elf_errno()));
+    exit(5);
+}
+
+
+/*
+ * The CRC used in gnu_debuglink, retrieved from
+ * http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files.
+ */
+
+static unsigned int
+gnu_debuglink_crc32(unsigned int crc, unsigned char *buf, size_t len) {
+    static const unsigned int crc32_table[256] = {
+        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+        0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+        0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+        0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+        0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+        0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+        0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+        0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+        0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+        0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+        0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+        0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+        0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+        0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+        0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+        0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+        0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+        0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+        0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+        0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+        0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+        0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+        0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+        0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+        0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+        0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+        0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+        0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+        0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+        0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+        0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+        0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+        0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+        0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+        0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+        0x2d02ef8d
+    };
+
+    unsigned char *end;
+
+    crc = ~crc & 0xffffffff;
+    for (end = buf + len; buf < end; ++buf) {
+        crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+    }
+    return ~crc & 0xffffffff;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/fix_empty_sec_hdr_flags/Makefile	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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.
+#  
+#
+
+# Rules to build fix_empty_sec_hdr_flags, used by various Makefiles on Solaris
+
+BUILDDIR = ../..
+include $(BUILDDIR)/common/Defs.gmk
+
+# Default name
+PROGRAM = fix_empty_sec_hdr_flags
+FIX_EMPTY_SEC_HDR_FLAGS_PROG = $(ABS_BUILDTOOLBINDIR)/$(PROGRAM)
+
+FIX_EMPTY_SEC_HDR_FLAGS_SRC     = fix_empty_sec_hdr_flags.c
+FIX_EMPTY_SEC_HDR_FLAGS_FLAGS   = 
+LIBS_FIX_EMPTY_SEC_HDR_FLAGS   += -lelf
+
+all: $(FIX_EMPTY_SEC_HDR_FLAGS)
+
+$(FIX_EMPTY_SEC_HDR_FLAGS_PROG): $(FIX_EMPTY_SEC_HDR_FLAGS_SRC)
+	$(MKDIR) -p $(BUILDTOOLBINDIR)
+	$(CC) -g -o $@ $< $(FIX_EMPTY_SEC_HDR_FLAGS_FLAGS) $(LIBS_FIX_EMPTY_SEC_HDR_FLAGS)
+
+clean::
+	$(RM) $(FIX_EMPTY_SEC_HDR_FLAGS_PROG)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/fix_empty_sec_hdr_flags/fix_empty_sec_hdr_flags.c	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Name:        fix_empty_sec_hdr_flags.c
+ *
+ * Description: Remove the SHF_ALLOC flag from "empty" section headers.
+ *     An "empty" section header has sh_addr == 0 and sh_size == 0.
+ *
+ *     This program is adapted from the example program shown on the
+ *     elf(3elf) man page and from code from the Solaris compiler
+ *     driver.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void failure(void);
+
+void
+main(int argc, char ** argv) {
+    void *        ehdr;           /* ELF header */
+    unsigned int  i;              /* section counter */
+    int           fd;             /* descriptor for file */
+    Elf *         elf;            /* ELF descriptor */
+    char *        elf_ident;      /* ELF identity string */
+    char *        elf_obj;        /* elf_obj file */
+    int           fix_count;      /* number of flags fixed */
+    int           is_elfclass64;  /* is an ELFCLASS64 file? */
+    Elf_Scn *     scn;            /* ELF section descriptor */
+    void *        shdr;           /* ELF section header */
+    Elf_Data *    shstrtab;       /* ELF section header string table */
+
+    if (argc != 2) {
+        (void) fprintf(stderr, "Usage: %s elf_obj\n", argv[0]);
+        exit(2);
+    }
+
+    /* open the elf_obj */
+    elf_obj = argv[1];
+    if ((fd = open(elf_obj, O_RDWR)) == -1) {
+        (void) fprintf(stderr, "%s: cannot open file.\n", elf_obj);
+        exit(3);
+    }
+
+    (void) printf("Opening '%s' for update\n", elf_obj);
+    (void) fflush(stdout);
+    (void) elf_version(EV_CURRENT);  /* coordinate ELF versions */
+
+    /* obtain the ELF descriptors from the input file */
+    if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
+        failure();
+    }
+
+    /* determine if ELFCLASS64 or not? */
+    elf_ident = elf_getident(elf, NULL);
+    is_elfclass64 = (elf_ident[EI_CLASS] == ELFCLASS64);
+
+    /* get the ELF header */
+    if (is_elfclass64) {
+        ehdr = elf64_getehdr(elf);
+    } else {
+        ehdr = elf32_getehdr(elf);
+    }
+    if (ehdr == NULL) {
+        failure();
+    }
+
+    /* get the ELF section descriptor */
+    if (is_elfclass64) {
+        scn = elf_getscn(elf, ((Elf64_Ehdr *) ehdr)->e_shstrndx);
+    } else {
+        scn = elf_getscn(elf, ((Elf32_Ehdr *) ehdr)->e_shstrndx);
+    }
+    if (scn == NULL) {
+        failure();
+    }
+
+    /* get the section header string table */
+    shstrtab = elf_getdata(scn, NULL);
+    if (shstrtab == NULL) {
+        failure();
+    }
+
+    fix_count = 0;
+
+    /* traverse the sections of the input file */
+    for (i = 1, scn = NULL; scn = elf_nextscn(elf, scn); i++) {
+        int    has_flag_set;  /* is SHF_ALLOC flag set? */
+        int    is_empty;      /* is section empty? */
+        char * name;          /* short hand pointer */
+
+        /* get the section header */
+        if (is_elfclass64) {
+            shdr = elf64_getshdr(scn);
+        } else {
+            shdr = elf32_getshdr(scn);
+        }
+        if (shdr == NULL) {
+            failure();
+        }
+
+        if (is_elfclass64) {
+            name = (char *)shstrtab->d_buf + ((Elf64_Shdr *) shdr)->sh_name;
+        } else {
+            name = (char *)shstrtab->d_buf + ((Elf32_Shdr *) shdr)->sh_name;
+        }
+
+        if (is_elfclass64) {
+            has_flag_set = ((Elf64_Shdr *) shdr)->sh_flags & SHF_ALLOC;
+            is_empty = ((Elf64_Shdr *) shdr)->sh_addr == 0 &&
+                ((Elf64_Shdr *) shdr)->sh_size == 0;
+        } else {
+            has_flag_set = ((Elf32_Shdr *) shdr)->sh_flags & SHF_ALLOC;
+            is_empty = ((Elf32_Shdr *) shdr)->sh_addr == 0 &&
+                ((Elf32_Shdr *) shdr)->sh_size == 0;
+        }
+
+        if (is_empty && has_flag_set) {
+            (void) printf("section[%u] '%s' is empty, "
+                "but SHF_ALLOC flag is set.\n", i, name);
+            (void) printf("Clearing the SHF_ALLOC flag.\n");
+
+            if (is_elfclass64) {
+                ((Elf64_Shdr *) shdr)->sh_flags &= ~SHF_ALLOC;
+            } else {
+                ((Elf32_Shdr *) shdr)->sh_flags &= ~SHF_ALLOC;
+            }
+            fix_count++;
+        }
+    }  /* end for each ELF section */
+
+    if (fix_count > 0) {
+        (void) printf("Saving %d updates to '%s'\n", fix_count, elf_obj);
+        (void) fflush(stdout);
+        (void) elf_update(elf, ELF_C_NULL);   /* recalc ELF memory structures */
+        (void) elf_update(elf, ELF_C_WRITE);  /* write out changes to ELF obj */
+    } else {
+        (void) printf("No SHF_ALLOC flags needed to be cleared.\n");
+    }
+
+    (void) elf_end(elf);                  /* done with ELF obj */
+    (void) close(fd);
+
+    (void) printf("Done %s '%s'\n",
+               (fix_count > 0) ? "updating" : "with", elf_obj);
+    (void) fflush(stdout);
+    exit(0);
+}  /* end main */
+
+
+static void
+failure() {
+    (void) fprintf(stderr, "%s\n", elf_errmsg(elf_errno()));
+    exit(6);
+}
--- a/src/macosx/classes/sun/awt/CGraphicsDevice.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/awt/CGraphicsDevice.java	Fri Jun 01 11:46:14 2012 -0700
@@ -40,7 +40,7 @@
     private final int displayID;
 
     // Array of all GraphicsConfig instances for this device
-    private final CGraphicsConfig[] configs;
+    private final GraphicsConfiguration[] configs;
 
     // Default config (temporarily hard coded)
     private final int DEFAULT_CONFIG = 0;
@@ -49,7 +49,7 @@
 
     public CGraphicsDevice(int displayID) {
         this.displayID = displayID;
-        configs = new CGraphicsConfig[] {
+        configs = new GraphicsConfiguration[] {
             CGLGraphicsConfig.getConfig(this, 0)
         };
     }
@@ -66,7 +66,7 @@
      */
     @Override
     public GraphicsConfiguration[] getConfigurations() {
-        return configs;
+        return configs.clone();
     }
 
     /**
--- a/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Fri Jun 01 11:46:14 2012 -0700
@@ -175,6 +175,10 @@
         return devices.values().toArray(new CGraphicsDevice[devices.values().size()]);
     }
 
+    public synchronized GraphicsDevice getScreenDevice(int displayID) {
+        return devices.get(displayID);
+    }
+
     @Override
     protected synchronized int getNumScreens() {
         return devices.size();
--- a/src/macosx/classes/sun/lwawt/LWComponentPeer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/LWComponentPeer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -377,7 +377,7 @@
     }
 
     @Override
-    public void dispose() {
+    public final void dispose() {
         if (disposed.compareAndSet(false, true)) {
             disposeImpl();
         }
@@ -965,8 +965,8 @@
 
     @Override
     public Image createImage(int w, int h) {
-        // TODO: accelerated image
-        return getGraphicsConfiguration().createCompatibleImage(w, h);
+        CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration();
+        return gc.createAcceleratedImage(getTarget(), w, h);
     }
 
     @Override
--- a/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -81,6 +81,18 @@
         firstChangeSkipped = true;
     }
 
+    @Override
+    protected final void disposeImpl() {
+        synchronized (getDelegateLock()) {
+            // visible caret has a timer thread which must be stopped
+            getTextComponent().getCaret().setVisible(false);
+        }
+        super.disposeImpl();
+    }
+
+    /**
+     * This method should be called under getDelegateLock().
+     */
     abstract JTextComponent getTextComponent();
 
     public Dimension getPreferredSize(final int rows, final int columns) {
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -68,7 +68,7 @@
 
     private Insets insets = new Insets(0, 0, 0, 0);
 
-    private int screenOn = -1;
+    private GraphicsDevice graphicsDevice;
     private GraphicsConfiguration graphicsConfig;
 
     private SurfaceData surfaceData;
@@ -887,17 +887,6 @@
         return 0;
     }
 
-    private static GraphicsConfiguration getScreenGraphicsConfig(int screen) {
-        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        GraphicsDevice[] gds = ge.getScreenDevices();
-        if (screen >= gds.length) {
-            // This could happen during device addition/removal. Use
-            // the default screen device in this case
-            return ge.getDefaultScreenDevice().getDefaultConfiguration();
-        }
-        return gds[screen].getDefaultConfiguration();
-    }
-
     /*
      * This method is called when window's graphics config is changed from
      * the app code (e.g. when the window is made non-opaque) or when
@@ -912,7 +901,7 @@
             }
             // If window's graphics config is changed from the app code, the
             // config correspond to the same device as before; when the window
-            // is moved by user, screenOn is updated in checkIfOnNewScreen().
+            // is moved by user, graphicsDevice is updated in checkIfOnNewScreen().
             // In either case, there's nothing to do with screenOn here
             graphicsConfig = gc;
         }
@@ -921,16 +910,17 @@
     }
 
     private void checkIfOnNewScreen() {
-        int windowScreen = platformWindow.getScreenImOn();
+        GraphicsDevice newGraphicsDevice = platformWindow.getGraphicsDevice();
         synchronized (getStateLock()) {
-            if (windowScreen == screenOn) {
+            if (graphicsDevice == newGraphicsDevice) {
                 return;
             }
-            screenOn = windowScreen;
+            graphicsDevice = newGraphicsDevice;
         }
 
         // TODO: DisplayChangedListener stuff
-        final GraphicsConfiguration newGC = getScreenGraphicsConfig(windowScreen);
+        final GraphicsConfiguration newGC = newGraphicsDevice.getDefaultConfiguration();
+
         if (!setGraphicsConfig(newGC)) return;
 
         SunToolkit.executeOnEventHandlerThread(getTarget(), new Runnable() {
--- a/src/macosx/classes/sun/lwawt/PlatformWindow.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/PlatformWindow.java	Fri Jun 01 11:46:14 2012 -0700
@@ -67,9 +67,9 @@
     public void setBounds(int x, int y, int w, int h);
 
     /*
-     * Returns the screen number where the window is.
+     * Returns the graphics device where the window is.
      */
-    public int getScreenImOn();
+    public GraphicsDevice getGraphicsDevice();
 
     /*
      * Returns the location of the window.
--- a/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -132,44 +132,31 @@
             this.setDefaultDragImage(component);
 
         // Get drag image (if any) as BufferedImage and convert that to CImage:
-        long  dragImage;
         Point dragImageOffset;
 
         if (fDragImage != null) {
-            BufferedImage bi = (fDragImage instanceof BufferedImage ? (BufferedImage) fDragImage : null);
+            try {
+                fDragCImage = CImage.getCreator().createFromImageImmediately(fDragImage);
+            } catch(Exception e) {
+                // image creation may fail for any reason
+                throw new InvalidDnDOperationException("Drag image can not be created.");
+            }
+            if (fDragCImage == null) {
+                throw new InvalidDnDOperationException("Drag image is not ready.");
+            }
 
-            if (bi == null) {
-                // Create a new buffered image:
-                int width  = fDragImage.getWidth(null);
-                int height = fDragImage.getHeight(null);
-                bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
-
-                // Draw drag image into the buffered image:
-                Graphics g = bi.getGraphics();
-                g.drawImage(fDragImage, 0, 0, null);
-                g.dispose();
-            }
-            /*   TODO:BG
-            fDragCImage = CImage.getCreator().createImage(bi);
-            dragImage = fDragCImage.getNSImage(); */
-            fDragCImage = null;
-            dragImage = 0L;
             dragImageOffset = fDragImageOffset;
         } else {
 
             fDragCImage = null;
-            dragImage = 0L;
             dragImageOffset = new Point(0, 0);
         }
 
-        // Get NS drag image instance if we have a drag image:
-        long nsDragImage = 0L; //TODO:BG (fDragCImage != null ? fDragCImage.getNSImage() : 0L);
-
         try {
             // Create native dragging source:
             final long nativeDragSource = createNativeDragSource(component, peer, nativeWindowPtr, transferable, triggerEvent,
                 (int) (dragOrigin.getX() + componentOffset.x), (int) (dragOrigin.getY() + componentOffset.y), extModifiers,
-                clickCount, timestamp, cursor, dragImage, dragImageOffset.x, dragImageOffset.y,
+                clickCount, timestamp, cursor, fDragCImage, dragImageOffset.x, dragImageOffset.y,
                 getDragSourceContext().getSourceActions(), formats, formatMap);
 
             if (nativeDragSource == 0)
@@ -495,7 +482,7 @@
     // Native support:
     private native long createNativeDragSource(Component component, ComponentPeer peer, long nativePeer, Transferable transferable,
         InputEvent triggerEvent, int dragPosX, int dragPosY, int extModifiers, int clickCount, long timestamp,
-        Cursor cursor, long nsDragImage, int dragImageOffsetX, int dragImageOffsetY,
+        Cursor cursor, CImage nsDragImage, int dragImageOffsetX, int dragImageOffsetY,
         int sourceActions, long[] formats, Map formatMap);
 
     private native void doDragging(long nativeDragSource);
--- a/src/macosx/classes/sun/lwawt/macosx/CImage.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CImage.java	Fri Jun 01 11:46:14 2012 -0700
@@ -93,32 +93,59 @@
             return createImageUsingNativeSize(nativeCreateNSImageFromImageName(name));
         }
 
-        // This is used to create a CImage from a Image
-        public CImage createFromImage(final Image image) {
+        private static int[] imageToArray(Image image, boolean prepareImage) {
             if (image == null) return null;
 
-            MediaTracker mt = new MediaTracker(new Label());
-            final int id = 0;
-            mt.addImage(image, id);
+            if (prepareImage && !(image instanceof BufferedImage)) {
+                final MediaTracker mt = new MediaTracker(new Label());
+                final int id = 0;
+                mt.addImage(image, id);
 
-            try {
-                mt.waitForID(id);
-            } catch (InterruptedException e) {
-            }
+                try {
+                    mt.waitForID(id);
+                } catch (InterruptedException e) {
+                    return null;
+                }
 
-            if (mt.isErrorID(id)) {
-                return null;
+                if (mt.isErrorID(id)) {
+                    return null;
+                }
             }
 
             int w = image.getWidth(null);
             int h = image.getHeight(null);
+
+            if (w < 0 || h < 0) {
+                return null;
+            }
+
             BufferedImage bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
             Graphics2D g2 = bimg.createGraphics();
             g2.setComposite(AlphaComposite.Src);
             g2.drawImage(image, 0, 0, null);
             g2.dispose();
-            int[] buffer = ((DataBufferInt)bimg.getRaster().getDataBuffer()).getData();
-            return new CImage(nativeCreateNSImageFromArray(buffer, w, h));
+
+            return ((DataBufferInt)bimg.getRaster().getDataBuffer()).getData();
+        }
+
+        public CImage createFromImageImmediately(final Image image) {
+            int[]  buffer = imageToArray(image, false);
+
+            if (buffer == null) {
+                return null;
+            }
+
+            return new CImage(nativeCreateNSImageFromArray(buffer, image.getWidth(null),
+                                                           image.getHeight(null)));
+        }
+
+        // This is used to create a CImage from a Image
+        public CImage createFromImage(final Image image) {
+            int[] buffer = imageToArray(image, true);
+            if (buffer == null) {
+                return null;
+            }
+            return new CImage(nativeCreateNSImageFromArray(buffer, image.getWidth(null), image.getHeight(null)));
         }
 
         static int getSelectorAsInt(final String fromString) {
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Fri Jun 01 11:46:14 2012 -0700
@@ -86,11 +86,10 @@
     }
 
     @Override
-    public int getScreenImOn() {
+    public GraphicsDevice getGraphicsDevice() {
         // REMIND: return the main screen for the initial implementation
-        CGraphicsConfig gc = (CGraphicsConfig)peer.getGraphicsConfiguration();
-        CGraphicsDevice device = gc.getDevice();
-        return device.getCoreGraphicsScreen();
+        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        return ge.getDefaultScreenDevice();
     }
 
     @Override
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Fri Jun 01 11:46:14 2012 -0700
@@ -63,7 +63,7 @@
     private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY);
     private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled);
 
-    private static native int nativeGetScreenNSWindowIsOn_AppKitThread(long nsWindowPtr);
+    private static native int nativeGetNSWindowDisplayID_AppKitThread(long nsWindowPtr);
 
     // Loger to report issues happened during execution but that do not affect functionality
     private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -451,13 +451,18 @@
         return new Point(nativeBounds.x, nativeBounds.y);
     }
 
-    @Override // PlatformWindow
-    public int getScreenImOn() {
-    // REMIND: we could also acquire screenID from the
-    // graphicsConfig.getDevice().getCoreGraphicsScreen()
-    // which might look a bit less natural but don't
-    // require new native accessor.
-        return nativeGetScreenNSWindowIsOn_AppKitThread(getNSWindowPtr());
+    @Override
+    public GraphicsDevice getGraphicsDevice() {
+        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        CGraphicsEnvironment cge = (CGraphicsEnvironment)ge;
+        int displayID = nativeGetNSWindowDisplayID_AppKitThread(getNSWindowPtr());
+        GraphicsDevice gd = cge.getScreenDevice(displayID);
+        if (gd == null) {
+            // this could possibly happen during device removal
+            // use the default screen device in this case
+            gd = ge.getDefaultScreenDevice();
+        }
+        return gd;
     }
 
     @Override // PlatformWindow
--- a/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java	Fri Jun 01 11:46:14 2012 -0700
@@ -41,10 +41,12 @@
     }
 
     public void enter() {
+        // Despite the naming of this method, on MacOS only one
+        // event is read and dispatched before this method returns.
+        // This call is non-blocking and does not wait for an event
         toolkit.startNativeNestedEventLoop();
     }
 
     public void exit() {
-        toolkit.stopNativeNestedEventLoop();
     }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Jun 01 11:46:14 2012 -0700
@@ -63,8 +63,15 @@
 
     private static native void initIDs();
 
+    // On Mac OS we don't need to actually start the new event loop since there is
+    // a mechanic that allows us to just reschedule the next event in a native event loop
+    // for immediate execution and because this method is being called repeatedly we just
+    // executing one such event every time we call this method
     static native void startNativeNestedEventLoop();
 
+    // Since we don't start an additional event loop this method is a no-op
+    // and shouldn't be called, left only for the better understanding of the concept on
+    // other OS'es
     static native void stopNativeNestedEventLoop();
 
     private static CInputMethodDescriptor sInputMethodDescriptor;
--- a/src/macosx/native/sun/awt/AWTEvent.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTEvent.m	Fri Jun 01 11:46:14 2012 -0700
@@ -124,7 +124,7 @@
     {0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},
     {0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE},
     {0x34, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_ENTER},
-    {0x35, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE},
+    {0x35, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE},
     {0x36, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
     {0x37, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_META},      // ****
     {0x38, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_SHIFT},     // ****
--- a/src/macosx/native/sun/awt/AWTWindow.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTWindow.m	Fri Jun 01 11:46:14 2012 -0700
@@ -652,7 +652,7 @@
         [[self.nsWindow standardWindowButton:NSWindowCloseButton] setEnabled: flag];
     }
 
-    if (IS(self.styleBits, MINIMIZABLE)) {        
+    if (IS(self.styleBits, MINIMIZABLE)) {
         [[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled: flag];
     }
 
@@ -1073,39 +1073,29 @@
 
 /*
  * Class:     sun_lwawt_macosx_CPlatformWindow
- * Method:    nativeGetScreenNSWindowIsOn_AppKitThread
+ * Method:    nativeGetDisplayID_AppKitThread
  * Signature: (J)I
  */
-JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetScreenNSWindowIsOn_1AppKitThread
+JNIEXPORT jint JNICALL
+Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowDisplayID_1AppKitThread
 (JNIEnv *env, jclass clazz, jlong windowPtr)
 {
-    jint index = -1;
+    jint ret; // CGDirectDisplayID
 
 JNF_COCOA_ENTER(env);
 AWT_ASSERT_APPKIT_THREAD;
 
-    NSWindow *nsWindow = OBJC(windowPtr);
-    NSScreen* screen = [nsWindow screen];
-
-    //+++gdb NOTE: This is using a linear search of the screens. If it should
-    //  prove to be a bottleneck, this can definitely be improved. However,
-    //  many screens should prove to be the exception, rather than the rule.
-    NSArray* screens = [NSScreen screens];
-    NSUInteger i;
-    for (i = 0; i < [screens count]; i++)
-    {
-        if ([[screens objectAtIndex:i] isEqualTo:screen])
-        {
-            index = i;
-            break;
-        }
-    }
+    NSWindow *window = OBJC(windowPtr);
+    NSScreen *screen = [window screen];
+    NSDictionary *deviceDescription = [screen deviceDescription];
+    NSNumber *displayID = [deviceDescription objectForKey:@"NSScreenNumber"];
+    ret = (jint)[displayID intValue];
 
 JNF_COCOA_EXIT(env);
-    return 1;
+
+    return ret;
 }
 
-
 /*
  * Class:     sun_lwawt_macosx_CPlatformWindow
  * Method:    _toggleFullScreenMode
--- a/src/macosx/native/sun/awt/CDragSource.h	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/CDragSource.h	Fri Jun 01 11:46:14 2012 -0700
@@ -63,7 +63,7 @@
     transferable:(jobject)jtransferable triggerEvent:(jobject)jtrigger
     dragPosX:(jint)dragPosX dragPosY:(jint)dragPosY modifiers:(jint)extModifiers clickCount:(jint)clickCount timeStamp:(jlong)timeStamp
     cursor:(jobject)jcursor
-    dragImage:(jlong)jnsdragimage dragImageOffsetX:(jint)jdragimageoffsetx dragImageOffsetY:(jint)jdragimageoffsety
+    dragImage:(jobject)jnsdragimage dragImageOffsetX:(jint)jdragimageoffsetx dragImageOffsetY:(jint)jdragimageoffsety
     sourceActions:(jint)jsourceactions formats:(jlongArray)jformats formatMap:(jobject)jformatmap;
 
 - (void)removeFromView:(JNIEnv *)env;
--- a/src/macosx/native/sun/awt/CDragSource.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/CDragSource.m	Fri Jun 01 11:46:14 2012 -0700
@@ -70,6 +70,7 @@
 
 JNF_CLASS_CACHE(DataTransfererClass, "sun/awt/datatransfer/DataTransferer");
 JNF_CLASS_CACHE(CDragSourceContextPeerClass, "sun/lwawt/macosx/CDragSourceContextPeer");
+JNF_CLASS_CACHE(CImageClass, "sun/lwawt/macosx/CImage");
 
 static NSDragOperation    sDragOperation;
 static NSPoint            sDraggingLocation;
@@ -87,7 +88,7 @@
     transferable:(jobject)jtransferable triggerEvent:(jobject)jtrigger
     dragPosX:(jint)dragPosX dragPosY:(jint)dragPosY modifiers:(jint)extModifiers clickCount:(jint)clickCount
     timeStamp:(jlong)timeStamp cursor:(jobject)jcursor
-    dragImage:(jlong)jnsdragimage dragImageOffsetX:(jint)jdragimageoffsetx dragImageOffsetY:(jint)jdragimageoffsety
+    dragImage:(jobject)jnsdragimage dragImageOffsetX:(jint)jdragimageoffsetx dragImageOffsetY:(jint)jdragimageoffsety
     sourceActions:(jint)jsourceactions formats:(jlongArray)jformats formatMap:(jobject)jformatmap
 {
     self = [super init];
@@ -107,8 +108,14 @@
         fTriggerEvent = JNFNewGlobalRef(env, jtrigger);
         fCursor = JNFNewGlobalRef(env, jcursor);
 
-        fDragImage = (NSImage*) jlong_to_ptr(jnsdragimage); // Double-casting prevents compiler 'different size' warning.
-        [fDragImage retain];
+        if (jnsdragimage) {
+            JNF_MEMBER_CACHE(nsImagePtr, CImageClass, "ptr", "J");
+            jlong imgPtr = JNFGetLongField(env, jnsdragimage, nsImagePtr);
+            fDragImage = (NSImage*) jlong_to_ptr(imgPtr); // Double-casting prevents compiler 'd$|//
+
+            [fDragImage retain];
+        }
+
         fDragImageOffset = NSMakePoint(jdragimageoffsetx, jdragimageoffsety);
 
         fSourceActions = jsourceactions;
--- a/src/macosx/native/sun/awt/CDragSourceContextPeer.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/CDragSourceContextPeer.m	Fri Jun 01 11:46:14 2012 -0700
@@ -39,7 +39,7 @@
 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDragSourceContextPeer_createNativeDragSource
   (JNIEnv *env, jobject jthis, jobject jcomponent, jobject jpeer, jlong jnativepeer, jobject jtransferable,
    jobject jtrigger, jint jdragposx, jint jdragposy, jint jextmodifiers, jint jclickcount, jlong jtimestamp,
-   jobject jcursor, jlong jnsdragimage, jint jdragimageoffsetx, jint jdragimageoffsety,
+   jobject jcursor, jobject jnsdragimage, jint jdragimageoffsetx, jint jdragimageoffsety,
    jint jsourceactions, jlongArray jformats, jobject jformatmap)
 {
     id controlObj = (id) jlong_to_ptr(jnativepeer);
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Fri Jun 01 11:46:14 2012 -0700
@@ -42,7 +42,6 @@
 @implementation AWTToolkit
 
 static long eventCount;
-static bool shouldKeepRunningNestedLoop = NO;
 
 + (long) getEventCount{
     return eventCount;
@@ -466,17 +465,13 @@
 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_startNativeNestedEventLoop
 (JNIEnv *env, jclass cls)
 {
-    if(!shouldKeepRunningNestedLoop) {
-        NSRunLoop *theRL = [NSRunLoop currentRunLoop];
-        NSApplication * app = [NSApplication sharedApplication];
-        shouldKeepRunningNestedLoop = YES;
-        while (shouldKeepRunningNestedLoop && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
-        {
-            NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
-            if (event != nil) {
-                [app sendEvent: event];
-            }
-        }
+    // Simply get the next event in native loop and pass it to execution
+    // We'll be called repeatedly so there's no need to block here
+    NSRunLoop *theRL = [NSRunLoop currentRunLoop];
+    NSApplication * app = [NSApplication sharedApplication];
+    NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
+    if (event != nil) {
+        [app sendEvent: event];
     }
 }
 
@@ -488,5 +483,5 @@
 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_stopNativeNestedEventLoop
 (JNIEnv *env, jclass cls)
 {
-    shouldKeepRunningNestedLoop = NO;
+//    At this moment it seems that this method should be no-op
 }
--- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m	Fri Jun 01 11:46:14 2012 -0700
@@ -312,10 +312,7 @@
 
     GLint contextVirtualScreen = [context currentVirtualScreen];
 #if USE_NSVIEW_FOR_SCRATCH
-    /* the scratch surface will be set to the view
-     * later on the flusher thread by OGLSD_SetScratchSurface.
-     */
-    //[context setView: scratchSurface];
+    [context setView: scratchSurface];
 #else
     [context
         setPixelBuffer: scratchSurface
--- a/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m	Thu May 31 14:06:48 2012 -0700
+++ b/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m	Fri Jun 01 11:46:14 2012 -0700
@@ -204,7 +204,8 @@
         if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
             return NULL;
         }
-    } else if ([NSOpenGLContext currentContext] == nil) {
+    // make sure our context is current
+    } else if ([NSOpenGLContext currentContext] != ctxinfo->context) {
         [ctxinfo->context makeCurrentContext];
     }
 
--- a/src/share/classes/java/lang/Integer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/lang/Integer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -330,7 +330,7 @@
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
         char[] buf = new char[size];
         getChars(i, size, buf);
-        return new String(0, size, buf);
+        return new String(buf, true);
     }
 
     /**
--- a/src/share/classes/java/lang/Long.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/lang/Long.java	Fri Jun 01 11:46:14 2012 -0700
@@ -266,7 +266,7 @@
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
         char[] buf = new char[size];
         getChars(i, size, buf);
-        return new String(0, size, buf);
+        return new String(buf, true);
     }
 
     /**
--- a/src/share/classes/java/lang/String.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/lang/String.java	Fri Jun 01 11:46:14 2012 -0700
@@ -22,10 +22,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package java.lang;
 
-import java.io.ObjectStreamClass;
 import java.io.ObjectStreamField;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
@@ -108,17 +106,10 @@
  */
 
 public final class String
-    implements java.io.Serializable, Comparable<String>, CharSequence
-{
+    implements java.io.Serializable, Comparable<String>, CharSequence {
     /** The value is used for character storage. */
     private final char value[];
 
-    /** The offset is the first index of the storage that is used. */
-    private final int offset;
-
-    /** The count is the number of characters in the String. */
-    private final int count;
-
     /** Cache the hash code for the string */
     private int hash; // Default to 0
 
@@ -138,7 +129,7 @@
      * string instance within the stream.
      */
     private static final ObjectStreamField[] serialPersistentFields =
-        new ObjectStreamField[0];
+            new ObjectStreamField[0];
 
     /**
      * Initializes a newly created {@code String} object so that it represents
@@ -146,8 +137,6 @@
      * unnecessary since Strings are immutable.
      */
     public String() {
-        this.offset = 0;
-        this.count = 0;
         this.value = new char[0];
     }
 
@@ -162,23 +151,8 @@
      *         A {@code String}
      */
     public String(String original) {
-        int size = original.count;
-        char[] originalValue = original.value;
-        char[] v;
-        if (originalValue.length > size) {
-            // The array representing the String is bigger than the new
-            // String itself.  Perhaps this constructor is being called
-            // in order to trim the baggage, so make a copy of the array.
-            int off = original.offset;
-            v = Arrays.copyOfRange(originalValue, off, off+size);
-        } else {
-            // The array representing the String is the same
-            // size as the String, so no point in making a copy.
-            v = originalValue;
-        }
-        this.offset = 0;
-        this.count = size;
-        this.value = v;
+        this.value = original.value;
+        this.hash = original.hash;
     }
 
     /**
@@ -191,10 +165,7 @@
      *         The initial value of the string
      */
     public String(char value[]) {
-        int size = value.length;
-        this.offset = 0;
-        this.count = size;
-        this.value = Arrays.copyOf(value, size);
+        this.value = Arrays.copyOf(value, value.length);
     }
 
     /**
@@ -229,8 +200,6 @@
         if (offset > value.length - count) {
             throw new StringIndexOutOfBoundsException(offset + count);
         }
-        this.offset = 0;
-        this.count = count;
         this.value = Arrays.copyOfRange(value, offset, offset+count);
     }
 
@@ -293,14 +262,12 @@
         for (int i = offset, j = 0; i < end; i++, j++) {
             int c = codePoints[i];
             if (Character.isBmpCodePoint(c))
-                v[j] = (char) c;
+                v[j] = (char)c;
             else
                 Character.toSurrogates(c, v, j++);
         }
 
-        this.value  = v;
-        this.count  = n;
-        this.offset = 0;
+        this.value = v;
     }
 
     /**
@@ -348,17 +315,15 @@
         char value[] = new char[count];
 
         if (hibyte == 0) {
-            for (int i = count ; i-- > 0 ;) {
-                value[i] = (char) (ascii[i + offset] & 0xff);
+            for (int i = count; i-- > 0;) {
+                value[i] = (char)(ascii[i + offset] & 0xff);
             }
         } else {
             hibyte <<= 8;
-            for (int i = count ; i-- > 0 ;) {
-                value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
+            for (int i = count; i-- > 0;) {
+                value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
             }
         }
-        this.offset = 0;
-        this.count = count;
         this.value = value;
     }
 
@@ -444,15 +409,11 @@
      * @since  JDK1.1
      */
     public String(byte bytes[], int offset, int length, String charsetName)
-        throws UnsupportedEncodingException
-    {
+            throws UnsupportedEncodingException {
         if (charsetName == null)
             throw new NullPointerException("charsetName");
         checkBounds(bytes, offset, length);
-        char[] v = StringCoding.decode(charsetName, bytes, offset, length);
-        this.offset = 0;
-        this.count = v.length;
-        this.value = v;
+        this.value = StringCoding.decode(charsetName, bytes, offset, length);
     }
 
     /**
@@ -489,10 +450,7 @@
         if (charset == null)
             throw new NullPointerException("charset");
         checkBounds(bytes, offset, length);
-        char[] v = StringCoding.decode(charset, bytes, offset, length);
-        this.offset = 0;
-        this.count = v.length;
-        this.value = v;
+        this.value =  StringCoding.decode(charset, bytes, offset, length);
     }
 
     /**
@@ -519,8 +477,7 @@
      * @since  JDK1.1
      */
     public String(byte bytes[], String charsetName)
-        throws UnsupportedEncodingException
-    {
+            throws UnsupportedEncodingException {
         this(bytes, 0, bytes.length, charsetName);
     }
 
@@ -576,10 +533,7 @@
      */
     public String(byte bytes[], int offset, int length) {
         checkBounds(bytes, offset, length);
-        char[] v  = StringCoding.decode(bytes, offset, length);
-        this.offset = 0;
-        this.count = v.length;
-        this.value = v;
+        this.value = StringCoding.decode(bytes, offset, length);
     }
 
     /**
@@ -612,10 +566,9 @@
      *         A {@code StringBuffer}
      */
     public String(StringBuffer buffer) {
-        String result = buffer.toString();
-        this.value = result.value;
-        this.count = result.count;
-        this.offset = result.offset;
+        synchronized(buffer) {
+            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
+        }
     }
 
     /**
@@ -634,18 +587,28 @@
      * @since  1.5
      */
     public String(StringBuilder builder) {
-        String result = builder.toString();
-        this.value = result.value;
-        this.count = result.count;
-        this.offset = result.offset;
+        this.value = Arrays.copyOf(builder.getValue(), builder.length());
     }
 
+    /*
+    * 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) {
+        // assert share : "unshared not supported";
+        this.value = value;
+    }
 
-    // Package private constructor which shares value array for speed.
-    String(int offset, int count, char value[]) {
-        this.value = value;
-        this.offset = offset;
-        this.count = count;
+    /**
+     * Package private constructor
+     *
+     * @deprecated Use {@link #String(char[],int,int)} instead.
+     */
+    @Deprecated
+    String(int offset, int count, char[] value) {
+        this(value, offset, count);
     }
 
     /**
@@ -657,7 +620,7 @@
      *          object.
      */
     public int length() {
-        return count;
+        return value.length;
     }
 
     /**
@@ -669,7 +632,7 @@
      * @since 1.6
      */
     public boolean isEmpty() {
-        return count == 0;
+        return value.length == 0;
     }
 
     /**
@@ -691,10 +654,10 @@
      *             string.
      */
     public char charAt(int index) {
-        if ((index < 0) || (index >= count)) {
+        if ((index < 0) || (index >= value.length)) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return value[index + offset];
+        return value[index];
     }
 
     /**
@@ -720,10 +683,10 @@
      * @since      1.5
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= count)) {
+        if ((index < 0) || (index >= value.length)) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointAtImpl(value, offset + index, offset + count);
+        return Character.codePointAtImpl(value, index, value.length);
     }
 
     /**
@@ -750,10 +713,10 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= count)) {
+        if ((i < 0) || (i >= value.length)) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBeforeImpl(value, offset + index, offset);
+        return Character.codePointBeforeImpl(value, index, 0);
     }
 
     /**
@@ -778,10 +741,10 @@
      * @since  1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
-        if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
+        if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex);
+        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
     }
 
     /**
@@ -805,11 +768,11 @@
      * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
-        if (index < 0 || index > count) {
+        if (index < 0 || index > value.length) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.offsetByCodePointsImpl(value, offset, count,
-                                                offset+index, codePointOffset) - offset;
+        return Character.offsetByCodePointsImpl(value, 0, value.length,
+                index, codePointOffset);
     }
 
     /**
@@ -817,7 +780,7 @@
      * This method doesn't perform any range checking.
      */
     void getChars(char dst[], int dstBegin) {
-        System.arraycopy(value, offset, dst, dstBegin, count);
+        System.arraycopy(value, 0, dst, dstBegin, value.length);
     }
 
     /**
@@ -854,14 +817,13 @@
         if (srcBegin < 0) {
             throw new StringIndexOutOfBoundsException(srcBegin);
         }
-        if (srcEnd > count) {
+        if (srcEnd > value.length) {
             throw new StringIndexOutOfBoundsException(srcEnd);
         }
         if (srcBegin > srcEnd) {
             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
         }
-        System.arraycopy(value, offset + srcBegin, dst, dstBegin,
-             srcEnd - srcBegin);
+        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
     }
 
     /**
@@ -912,15 +874,15 @@
         if (srcBegin < 0) {
             throw new StringIndexOutOfBoundsException(srcBegin);
         }
-        if (srcEnd > count) {
+        if (srcEnd > value.length) {
             throw new StringIndexOutOfBoundsException(srcEnd);
         }
         if (srcBegin > srcEnd) {
             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
         }
         int j = dstBegin;
-        int n = offset + srcEnd;
-        int i = offset + srcBegin;
+        int n = srcEnd;
+        int i = srcBegin;
         char[] val = value;   /* avoid getfield opcode */
 
         while (i < n) {
@@ -949,10 +911,9 @@
      * @since  JDK1.1
      */
     public byte[] getBytes(String charsetName)
-        throws UnsupportedEncodingException
-    {
+            throws UnsupportedEncodingException {
         if (charsetName == null) throw new NullPointerException();
-        return StringCoding.encode(charsetName, value, offset, count);
+        return StringCoding.encode(charsetName, value, 0, value.length);
     }
 
     /**
@@ -975,7 +936,7 @@
      */
     public byte[] getBytes(Charset charset) {
         if (charset == null) throw new NullPointerException();
-        return StringCoding.encode(charset, value, offset, count);
+        return StringCoding.encode(charset, value, 0, value.length);
     }
 
     /**
@@ -992,7 +953,7 @@
      * @since      JDK1.1
      */
     public byte[] getBytes() {
-        return StringCoding.encode(value, offset, count);
+        return StringCoding.encode(value, 0, value.length);
     }
 
     /**
@@ -1015,16 +976,16 @@
             return true;
         }
         if (anObject instanceof String) {
-            String anotherString = (String)anObject;
-            int n = count;
-            if (n == anotherString.count) {
+            String anotherString = (String) anObject;
+            int n = value.length;
+            if (n == anotherString.value.length) {
                 char v1[] = value;
                 char v2[] = anotherString.value;
-                int i = offset;
-                int j = anotherString.offset;
+                int i = 0;
                 while (n-- != 0) {
-                    if (v1[i++] != v2[j++])
-                        return false;
+                    if (v1[i] != v2[i])
+                            return false;
+                    i++;
                 }
                 return true;
             }
@@ -1047,8 +1008,8 @@
      * @since  1.4
      */
     public boolean contentEquals(StringBuffer sb) {
-        synchronized(sb) {
-            return contentEquals((CharSequence)sb);
+        synchronized (sb) {
+            return contentEquals((CharSequence) sb);
         }
     }
 
@@ -1067,18 +1028,18 @@
      * @since  1.5
      */
     public boolean contentEquals(CharSequence cs) {
-        if (count != cs.length())
+        if (value.length != cs.length())
             return false;
         // Argument is a StringBuffer, StringBuilder
         if (cs instanceof AbstractStringBuilder) {
             char v1[] = value;
-            char v2[] = ((AbstractStringBuilder)cs).getValue();
-            int i = offset;
-            int j = 0;
-            int n = count;
+            char v2[] = ((AbstractStringBuilder) cs).getValue();
+            int i = 0;
+            int n = value.length;
             while (n-- != 0) {
-                if (v1[i++] != v2[j++])
+                if (v1[i] != v2[i])
                     return false;
+                i++;
             }
             return true;
         }
@@ -1087,12 +1048,12 @@
             return true;
         // Argument is a generic CharSequence
         char v1[] = value;
-        int i = offset;
-        int j = 0;
-        int n = count;
+        int i = 0;
+        int n = value.length;
         while (n-- != 0) {
-            if (v1[i++] != cs.charAt(j++))
+            if (v1[i] != cs.charAt(i))
                 return false;
+            i++;
         }
         return true;
     }
@@ -1126,9 +1087,10 @@
      * @see  #equals(Object)
      */
     public boolean equalsIgnoreCase(String anotherString) {
-        return (this == anotherString) ? true :
-               (anotherString != null) && (anotherString.count == count) &&
-               regionMatches(true, 0, anotherString, 0, count);
+        return (this == anotherString) ? true
+                : (anotherString != null)
+                && (anotherString.value.length == value.length)
+                && regionMatches(true, 0, anotherString, 0, value.length);
     }
 
     /**
@@ -1173,33 +1135,20 @@
      *          lexicographically greater than the string argument.
      */
     public int compareTo(String anotherString) {
-        int len1 = count;
-        int len2 = anotherString.count;
-        int n = Math.min(len1, len2);
+        int len1 = value.length;
+        int len2 = anotherString.value.length;
+        int lim = Math.min(len1, len2);
         char v1[] = value;
         char v2[] = anotherString.value;
-        int i = offset;
-        int j = anotherString.offset;
 
-        if (i == j) {
-            int k = i;
-            int lim = n + i;
-            while (k < lim) {
-                char c1 = v1[k];
-                char c2 = v2[k];
-                if (c1 != c2) {
-                    return c1 - c2;
-                }
-                k++;
+        int k = 0;
+        while (k < lim) {
+            char c1 = v1[k];
+            char c2 = v2[k];
+            if (c1 != c2) {
+                return c1 - c2;
             }
-        } else {
-            while (n-- != 0) {
-                char c1 = v1[i++];
-                char c2 = v2[j++];
-                if (c1 != c2) {
-                    return c1 - c2;
-                }
-            }
+            k++;
         }
         return len1 - len2;
     }
@@ -1219,7 +1168,7 @@
     public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                          = new CaseInsensitiveComparator();
     private static class CaseInsensitiveComparator
-                         implements Comparator<String>, java.io.Serializable {
+            implements Comparator<String>, java.io.Serializable {
         // use serialVersionUID from JDK 1.2.2 for interoperability
         private static final long serialVersionUID = 8575799808933029326L;
 
@@ -1303,14 +1252,15 @@
      *          <code>false</code> otherwise.
      */
     public boolean regionMatches(int toffset, String other, int ooffset,
-                                 int len) {
+            int len) {
         char ta[] = value;
-        int to = offset + toffset;
+        int to = toffset;
         char pa[] = other.value;
-        int po = other.offset + ooffset;
+        int po = ooffset;
         // Note: toffset, ooffset, or len might be near -1>>>1.
-        if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len)
-            || (ooffset > (long)other.count - len)) {
+        if ((ooffset < 0) || (toffset < 0)
+                || (toffset > (long)value.length - len)
+                || (ooffset > (long)other.value.length - len)) {
             return false;
         }
         while (len-- > 0) {
@@ -1348,7 +1298,7 @@
      * integer <i>k</i> less than <tt>len</tt> such that:
      * <blockquote><pre>
      * Character.toLowerCase(this.charAt(toffset+k)) !=
-               Character.toLowerCase(other.charAt(ooffset+k))
+     Character.toLowerCase(other.charAt(ooffset+k))
      * </pre></blockquote>
      * and:
      * <blockquote><pre>
@@ -1372,14 +1322,15 @@
      *          argument.
      */
     public boolean regionMatches(boolean ignoreCase, int toffset,
-                           String other, int ooffset, int len) {
+            String other, int ooffset, int len) {
         char ta[] = value;
-        int to = offset + toffset;
+        int to = toffset;
         char pa[] = other.value;
-        int po = other.offset + ooffset;
+        int po = ooffset;
         // Note: toffset, ooffset, or len might be near -1>>>1.
-        if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) ||
-                (ooffset > (long)other.count - len)) {
+        if ((ooffset < 0) || (toffset < 0)
+                || (toffset > (long)value.length - len)
+                || (ooffset > (long)other.value.length - len)) {
             return false;
         }
         while (len-- > 0) {
@@ -1430,12 +1381,12 @@
      */
     public boolean startsWith(String prefix, int toffset) {
         char ta[] = value;
-        int to = offset + toffset;
+        int to = toffset;
         char pa[] = prefix.value;
-        int po = prefix.offset;
-        int pc = prefix.count;
+        int po = 0;
+        int pc = prefix.value.length;
         // Note: toffset might be near -1>>>1.
-        if ((toffset < 0) || (toffset > count - pc)) {
+        if ((toffset < 0) || (toffset > value.length - pc)) {
             return false;
         }
         while (--pc >= 0) {
@@ -1475,7 +1426,7 @@
      *          as determined by the {@link #equals(Object)} method.
      */
     public boolean endsWith(String suffix) {
-        return startsWith(suffix, count - suffix.count);
+        return startsWith(suffix, value.length - suffix.value.length);
     }
 
     /**
@@ -1493,13 +1444,11 @@
      */
     public int hashCode() {
         int h = hash;
-        if (h == 0 && count > 0) {
-            int off = offset;
+        if (h == 0 && value.length > 0) {
             char val[] = value;
-            int len = count;
 
-            for (int i = 0; i < len; i++) {
-                h = 31*h + val[off++];
+            for (int i = 0; i < value.length; i++) {
+                h = 31 * h + val[i];
             }
             hash = h;
         }
@@ -1574,9 +1523,10 @@
      *          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 >= count) {
+        } else if (fromIndex >= max) {
             // Note: fromIndex might be near -1>>>1.
             return -1;
         }
@@ -1585,11 +1535,9 @@
             // handle most cases here (ch is a BMP code point or a
             // negative value (invalid code point))
             final char[] value = this.value;
-            final int offset = this.offset;
-            final int max = offset + count;
-            for (int i = offset + fromIndex; i < max ; i++) {
+            for (int i = fromIndex; i < max; i++) {
                 if (value[i] == ch) {
-                    return i - offset;
+                    return i;
                 }
             }
             return -1;
@@ -1604,13 +1552,12 @@
     private int indexOfSupplementary(int ch, int fromIndex) {
         if (Character.isValidCodePoint(ch)) {
             final char[] value = this.value;
-            final int offset = this.offset;
             final char hi = Character.highSurrogate(ch);
             final char lo = Character.lowSurrogate(ch);
-            final int max = offset + count - 1;
-            for (int i = offset + fromIndex; i < max; i++) {
-                if (value[i] == hi && value[i+1] == lo) {
-                    return i - offset;
+            final int max = value.length - 1;
+            for (int i = fromIndex; i < max; i++) {
+                if (value[i] == hi && value[i + 1] == lo) {
+                    return i;
                 }
             }
         }
@@ -1641,7 +1588,7 @@
      *          <code>-1</code> if the character does not occur.
      */
     public int lastIndexOf(int ch) {
-        return lastIndexOf(ch, count - 1);
+        return lastIndexOf(ch, value.length - 1);
     }
 
     /**
@@ -1683,11 +1630,10 @@
             // handle most cases here (ch is a BMP code point or a
             // negative value (invalid code point))
             final char[] value = this.value;
-            final int offset = this.offset;
-            int i = offset + Math.min(fromIndex, count - 1);
-            for (; i >= offset ; i--) {
+            int i = Math.min(fromIndex, value.length - 1);
+            for (; i >= 0; i--) {
                 if (value[i] == ch) {
-                    return i - offset;
+                    return i;
                 }
             }
             return -1;
@@ -1702,13 +1648,12 @@
     private int lastIndexOfSupplementary(int ch, int fromIndex) {
         if (Character.isValidCodePoint(ch)) {
             final char[] value = this.value;
-            final int offset = this.offset;
             char hi = Character.highSurrogate(ch);
             char lo = Character.lowSurrogate(ch);
-            int i = offset + Math.min(fromIndex, count - 2);
-            for (; i >= offset; i--) {
-                if (value[i] == hi && value[i+1] == lo) {
-                    return i - offset;
+            int i = Math.min(fromIndex, value.length - 2);
+            for (; i >= 0; i--) {
+                if (value[i] == hi && value[i + 1] == lo) {
+                    return i;
                 }
             }
         }
@@ -1750,8 +1695,8 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        return indexOf(value, offset, count,
-                       str.value, str.offset, str.count, fromIndex);
+        return indexOf(value, 0, value.length,
+                str.value, 0, str.value.length, fromIndex);
     }
 
     /**
@@ -1768,8 +1713,8 @@
      * @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) {
+            char[] target, int targetOffset, int targetCount,
+            int fromIndex) {
         if (fromIndex >= sourceCount) {
             return (targetCount == 0 ? sourceCount : -1);
         }
@@ -1780,7 +1725,7 @@
             return fromIndex;
         }
 
-        char first  = target[targetOffset];
+        char first = target[targetOffset];
         int max = sourceOffset + (sourceCount - targetCount);
 
         for (int i = sourceOffset + fromIndex; i <= max; i++) {
@@ -1793,8 +1738,8 @@
             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++);
+                for (int k = targetOffset + 1; j < end && source[j]
+                        == target[k]; j++, k++);
 
                 if (j == end) {
                     /* Found whole string. */
@@ -1821,7 +1766,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str) {
-        return lastIndexOf(str, count);
+        return lastIndexOf(str, value.length);
     }
 
     /**
@@ -1841,8 +1786,8 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        return lastIndexOf(value, offset, count,
-                           str.value, str.offset, str.count, fromIndex);
+        return lastIndexOf(value, 0, value.length,
+                str.value, 0, str.value.length, fromIndex);
     }
 
     /**
@@ -1859,8 +1804,8 @@
      * @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) {
+            char[] target, int targetOffset, int targetCount,
+            int fromIndex) {
         /*
          * Check arguments; return immediately where possible. For
          * consistency, don't check for null str.
@@ -1882,7 +1827,7 @@
         int min = sourceOffset + targetCount - 1;
         int i = min + fromIndex;
 
-    startSearchForLastChar:
+        startSearchForLastChar:
         while (true) {
             while (i >= min && source[i] != strLastChar) {
                 i--;
@@ -1922,7 +1867,14 @@
      *             length of this <code>String</code> object.
      */
     public String substring(int beginIndex) {
-        return substring(beginIndex, count);
+        if (beginIndex < 0) {
+            throw new StringIndexOutOfBoundsException(beginIndex);
+        }
+        int subLen = value.length - beginIndex;
+        if (subLen < 0) {
+            throw new StringIndexOutOfBoundsException(subLen);
+        }
+        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
     }
 
     /**
@@ -1951,14 +1903,15 @@
         if (beginIndex < 0) {
             throw new StringIndexOutOfBoundsException(beginIndex);
         }
-        if (endIndex > count) {
+        if (endIndex > value.length) {
             throw new StringIndexOutOfBoundsException(endIndex);
         }
-        if (beginIndex > endIndex) {
-            throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
+        int subLen = endIndex - beginIndex;
+        if (subLen < 0) {
+            throw new StringIndexOutOfBoundsException(subLen);
         }
-        return ((beginIndex == 0) && (endIndex == count)) ? this :
-            new String(offset + beginIndex, endIndex - beginIndex, value);
+        return ((beginIndex == 0) && (endIndex == value.length)) ? this
+                : new String(value, beginIndex, subLen);
     }
 
     /**
@@ -2018,10 +1971,10 @@
         if (otherLen == 0) {
             return this;
         }
-        char buf[] = new char[count + otherLen];
-        getChars(0, count, buf, 0);
-        str.getChars(0, otherLen, buf, count);
-        return new String(0, count + otherLen, buf);
+        int len = value.length;
+        char buf[] = Arrays.copyOf(value, len + otherLen);
+        str.getChars(buf, len);
+        return new String(buf, true);
     }
 
     /**
@@ -2055,27 +2008,26 @@
      */
     public String replace(char oldChar, char newChar) {
         if (oldChar != newChar) {
-            int len = count;
+            int len = value.length;
             int i = -1;
             char[] val = value; /* avoid getfield opcode */
-            int off = offset;   /* avoid getfield opcode */
 
             while (++i < len) {
-                if (val[off + i] == oldChar) {
+                if (val[i] == oldChar) {
                     break;
                 }
             }
             if (i < len) {
                 char buf[] = new char[len];
-                for (int j = 0 ; j < i ; j++) {
-                    buf[j] = val[off+j];
+                for (int j = 0; j < i; j++) {
+                    buf[j] = val[j];
                 }
                 while (i < len) {
-                    char c = val[off + i];
+                    char c = val[i];
                     buf[i] = (c == oldChar) ? newChar : c;
                     i++;
                 }
-                return new String(0, len, buf);
+                return new String(buf, true);
             }
         }
         return this;
@@ -2226,7 +2178,7 @@
      */
     public String replace(CharSequence target, CharSequence replacement) {
         return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
-            this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
+                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
     }
 
     /**
@@ -2311,13 +2263,13 @@
      */
     public String[] split(String regex, int limit) {
         /* fastpath if the regex is a
-           (1)one-char String and this character is not one of the
-              RegEx's meta characters ".$|()[{^?*+\\", or
-           (2)two-char String and the first char is the backslash and
-              the second is not the ascii digit or ascii letter.
-        */
+         (1)one-char String and this character is not one of the
+            RegEx's meta characters ".$|()[{^?*+\\", or
+         (2)two-char String and the first char is the backslash and
+            the second is not the ascii digit or ascii letter.
+         */
         char ch = 0;
-        if (((regex.count == 1 &&
+        if (((regex.value.length == 1 &&
              ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
              (regex.length() == 2 &&
               regex.charAt(0) == '\\' &&
@@ -2337,23 +2289,23 @@
                     off = next + 1;
                 } else {    // last one
                     //assert (list.size() == limit - 1);
-                    list.add(substring(off, count));
-                    off = count;
+                    list.add(substring(off, value.length));
+                    off = value.length;
                     break;
                 }
             }
             // If no match was found, return this
             if (off == 0)
-                return new String[] { this };
+                return new String[]{this};
 
             // Add remaining segment
             if (!limited || list.size() < limit)
-                list.add(substring(off, count));
+                list.add(substring(off, value.length));
 
             // Construct result
             int resultSize = list.size();
             if (limit == 0)
-                while (resultSize > 0 && list.get(resultSize-1).length() == 0)
+                while (resultSize > 0 && list.get(resultSize - 1).length() == 0)
                     resultSize--;
             String[] result = new String[resultSize];
             return list.subList(0, resultSize).toArray(result);
@@ -2460,14 +2412,15 @@
             throw new NullPointerException();
         }
 
-        int     firstUpper;
+        int firstUpper;
+        final int len = value.length;
 
         /* Now check if there are any characters that need to be changed. */
         scan: {
-            for (firstUpper = 0 ; firstUpper < count; ) {
-                char c = value[offset+firstUpper];
-                if ((c >= Character.MIN_HIGH_SURROGATE) &&
-                    (c <= Character.MAX_HIGH_SURROGATE)) {
+            for (firstUpper = 0 ; firstUpper < len; ) {
+                char c = value[firstUpper];
+                if ((c >= Character.MIN_HIGH_SURROGATE)
+                        && (c <= Character.MAX_HIGH_SURROGATE)) {
                     int supplChar = codePointAt(firstUpper);
                     if (supplChar != Character.toLowerCase(supplChar)) {
                         break scan;
@@ -2483,24 +2436,24 @@
             return this;
         }
 
-        char[]  result = new char[count];
-        int     resultOffset = 0;  /* result may grow, so i+resultOffset
-                                    * is the write location in result */
+        char[] result = new char[len];
+        int resultOffset = 0;  /* result may grow, so i+resultOffset
+                                * is the write location in result */
 
         /* Just copy the first few lowerCase characters. */
-        System.arraycopy(value, offset, result, 0, firstUpper);
+        System.arraycopy(value, 0, result, 0, firstUpper);
 
         String lang = locale.getLanguage();
         boolean localeDependent =
-            (lang == "tr" || lang == "az" || lang == "lt");
+                (lang == "tr" || lang == "az" || lang == "lt");
         char[] lowerCharArray;
         int lowerChar;
         int srcChar;
         int srcCount;
-        for (int i = firstUpper; i < count; i += srcCount) {
-            srcChar = (int)value[offset+i];
-            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
-                (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
+        for (int i = firstUpper; i < len; i += srcCount) {
+            srcChar = (int)value[i];
+            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE
+                    && (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                 srcChar = codePointAt(i);
                 srcCount = Character.charCount(srcChar);
             } else {
@@ -2513,16 +2466,16 @@
             } else {
                 lowerChar = Character.toLowerCase(srcChar);
             }
-            if ((lowerChar == Character.ERROR) ||
-                (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
+            if ((lowerChar == Character.ERROR)
+                    || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                 if (lowerChar == Character.ERROR) {
-                     if (!localeDependent && srcChar == '\u0130') {
-                         lowerCharArray =
-                             ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH);
-                     } else {
+                    if (!localeDependent && srcChar == '\u0130') {
                         lowerCharArray =
-                            ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
-                     }
+                                ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH);
+                    } else {
+                        lowerCharArray =
+                                ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
+                    }
                 } else if (srcCount == 2) {
                     resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
                     continue;
@@ -2534,19 +2487,18 @@
                 int mapLen = lowerCharArray.length;
                 if (mapLen > srcCount) {
                     char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0,
-                        i + resultOffset);
+                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                     result = result2;
                 }
-                for (int x=0; x<mapLen; ++x) {
-                    result[i+resultOffset+x] = lowerCharArray[x];
+                for (int x = 0; x < mapLen; ++x) {
+                    result[i + resultOffset + x] = lowerCharArray[x];
                 }
                 resultOffset += (mapLen - srcCount);
             } else {
-                result[i+resultOffset] = (char)lowerChar;
+                result[i + resultOffset] = (char)lowerChar;
             }
         }
-        return new String(0, count+resultOffset, result);
+        return new String(result, 0, len + resultOffset);
     }
 
     /**
@@ -2625,23 +2577,24 @@
             throw new NullPointerException();
         }
 
-        int     firstLower;
+        int firstLower;
+        final int len = value.length;
 
         /* Now check if there are any characters that need to be changed. */
         scan: {
-            for (firstLower = 0 ; firstLower < count; ) {
-                int c = (int)value[offset+firstLower];
+           for (firstLower = 0 ; firstLower < len; ) {
+                int c = (int)value[firstLower];
                 int srcCount;
-                if ((c >= Character.MIN_HIGH_SURROGATE) &&
-                    (c <= Character.MAX_HIGH_SURROGATE)) {
+                if ((c >= Character.MIN_HIGH_SURROGATE)
+                        && (c <= Character.MAX_HIGH_SURROGATE)) {
                     c = codePointAt(firstLower);
                     srcCount = Character.charCount(c);
                 } else {
                     srcCount = 1;
                 }
                 int upperCaseChar = Character.toUpperCaseEx(c);
-                if ((upperCaseChar == Character.ERROR) ||
-                    (c != upperCaseChar)) {
+                if ((upperCaseChar == Character.ERROR)
+                        || (c != upperCaseChar)) {
                     break scan;
                 }
                 firstLower += srcCount;
@@ -2649,22 +2602,22 @@
             return this;
         }
 
-        char[]  result       = new char[count]; /* may grow */
-        int     resultOffset = 0;  /* result may grow, so i+resultOffset
-                                    * is the write location in result */
+        char[] result = new char[len]; /* may grow */
+        int resultOffset = 0;  /* result may grow, so i+resultOffset
+         * is the write location in result */
 
         /* Just copy the first few upperCase characters. */
-        System.arraycopy(value, offset, result, 0, firstLower);
+        System.arraycopy(value, 0, result, 0, firstLower);
 
         String lang = locale.getLanguage();
         boolean localeDependent =
-            (lang == "tr" || lang == "az" || lang == "lt");
+                (lang == "tr" || lang == "az" || lang == "lt");
         char[] upperCharArray;
         int upperChar;
         int srcChar;
         int srcCount;
-        for (int i = firstLower; i < count; i += srcCount) {
-            srcChar = (int)value[offset+i];
+        for (int i = firstLower; i < len; i += srcCount) {
+            srcChar = (int)value[i];
             if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
                 (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                 srcChar = codePointAt(i);
@@ -2677,12 +2630,12 @@
             } else {
                 upperChar = Character.toUpperCaseEx(srcChar);
             }
-            if ((upperChar == Character.ERROR) ||
-                (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
+            if ((upperChar == Character.ERROR)
+                    || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                 if (upperChar == Character.ERROR) {
                     if (localeDependent) {
                         upperCharArray =
-                            ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
+                                ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
                     } else {
                         upperCharArray = Character.toUpperCaseCharArray(srcChar);
                     }
@@ -2697,19 +2650,18 @@
                 int mapLen = upperCharArray.length;
                 if (mapLen > srcCount) {
                     char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0,
-                        i + resultOffset);
+                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                     result = result2;
                 }
-                for (int x=0; x<mapLen; ++x) {
-                    result[i+resultOffset+x] = upperCharArray[x];
+                for (int x = 0; x < mapLen; ++x) {
+                    result[i + resultOffset + x] = upperCharArray[x];
                 }
                 resultOffset += (mapLen - srcCount);
             } else {
-                result[i+resultOffset] = (char)upperChar;
+                result[i + resultOffset] = (char)upperChar;
             }
         }
-        return new String(0, count+resultOffset, result);
+        return new String(result, 0, len + resultOffset);
     }
 
     /**
@@ -2767,18 +2719,17 @@
      *          trailing white space.
      */
     public String trim() {
-        int len = count;
+        int len = value.length;
         int st = 0;
-        int off = offset;      /* avoid getfield opcode */
         char[] val = value;    /* avoid getfield opcode */
 
-        while ((st < len) && (val[off + st] <= ' ')) {
+        while ((st < len) && (val[st] <= ' ')) {
             st++;
         }
-        while ((st < len) && (val[off + len - 1] <= ' ')) {
+        while ((st < len) && (val[len - 1] <= ' ')) {
             len--;
         }
-        return ((st > 0) || (len < count)) ? substring(st, len) : this;
+        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
     }
 
     /**
@@ -2798,8 +2749,9 @@
      *          the character sequence represented by this string.
      */
     public char[] toCharArray() {
-        char result[] = new char[count];
-        getChars(0, count, result, 0);
+        // 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;
     }
 
@@ -2841,7 +2793,7 @@
      * @see  java.util.Formatter
      * @since  1.5
      */
-    public static String format(String format, Object ... args) {
+    public static String format(String format, Object... args) {
         return new Formatter().format(format, args).toString();
     }
 
@@ -2885,7 +2837,7 @@
      * @see  java.util.Formatter
      * @since  1.5
      */
-    public static String format(Locale l, String format, Object ... args) {
+    public static String format(Locale l, String format, Object... args) {
         return new Formatter(l).format(format, args).toString();
     }
 
@@ -2965,7 +2917,7 @@
      *          character array.
      */
     public static String copyValueOf(char data[]) {
-        return copyValueOf(data, 0, data.length);
+        return new String(data);
     }
 
     /**
@@ -2990,7 +2942,7 @@
      */
     public static String valueOf(char c) {
         char data[] = {c};
-        return new String(0, 1, data);
+        return new String(data, true);
     }
 
     /**
@@ -3074,4 +3026,78 @@
      */
     public native String intern();
 
+    /**
+     * Seed value used for each alternative hash calculated.
+     */
+    private static final int HASHING_SEED;
+
+    static {
+        long nanos = System.nanoTime();
+        long now = System.currentTimeMillis();
+        int SEED_MATERIAL[] = {
+                System.identityHashCode(String.class),
+                System.identityHashCode(System.class),
+                (int) (nanos >>> 32),
+                (int) nanos,
+                (int) (now >>> 32),
+                (int) now,
+                (int) (System.nanoTime() >>> 2)
+        };
+
+        // Use murmur3 to scramble the seeding material.
+        // Inline implementation to avoid loading classes
+        int h1 = 0;
+
+        // body
+        for (int k1 : SEED_MATERIAL) {
+            k1 *= 0xcc9e2d51;
+            k1 = (k1 << 15) | (k1 >>> 17);
+            k1 *= 0x1b873593;
+
+            h1 ^= k1;
+            h1 = (h1 << 13) | (h1 >>> 19);
+            h1 = h1 * 5 + 0xe6546b64;
+        }
+
+        // tail (always empty, as body is always 32-bit chunks)
+
+        // finalization
+
+        h1 ^= SEED_MATERIAL.length * 4;
+
+        // finalization mix force all bits of a hash block to avalanche
+        h1 ^= h1 >>> 16;
+        h1 *= 0x85ebca6b;
+        h1 ^= h1 >>> 13;
+        h1 *= 0xc2b2ae35;
+        h1 ^= h1 >>> 16;
+
+        HASHING_SEED = h1;
+    }
+
+    /**
+     * Cached value of the alternative hashing algorithm result
+     */
+    private transient int hash32 = 0;
+
+    /**
+     * Calculates a 32-bit hash value for this string.
+     *
+     * @return a 32-bit hash value for this string.
+     */
+    int hash32() {
+        int h = hash32;
+        if (0 == h) {
+           // harmless data race on hash32 here.
+           h = sun.misc.Hashing.murmur3_32(HASHING_SEED, value, 0, value.length);
+
+           // ensure result is not zero to avoid recalcing
+           h = (0 != h) ? h : 1;
+
+           hash32 = h;
+        }
+
+        return h;
+    }
+
 }
--- a/src/share/classes/java/lang/StringCoding.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/lang/StringCoding.java	Fri Jun 01 11:46:14 2012 -0700
@@ -250,6 +250,7 @@
     static char[] decode(byte[] ba, int off, int len) {
         String csn = Charset.defaultCharset().name();
         try {
+            // use charset name decode() variant which provides caching.
             return decode(csn, ba, off, len);
         } catch (UnsupportedEncodingException x) {
             warnUnsupportedCharset(csn);
@@ -382,6 +383,7 @@
     static byte[] encode(char[] ca, int off, int len) {
         String csn = Charset.defaultCharset().name();
         try {
+            // use charset name encode() variant which provides caching.
             return encode(csn, ca, off, len);
         } catch (UnsupportedEncodingException x) {
             warnUnsupportedCharset(csn);
--- a/src/share/classes/java/lang/System.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/lang/System.java	Fri Jun 01 11:46:14 2012 -0700
@@ -1196,6 +1196,9 @@
             public StackTraceElement getStackTraceElement(Throwable t, int i) {
                 return t.getStackTraceElement(i);
             }
+            public int getStringHash32(String string) {
+                return string.hash32();
+            }
         });
     }
 
--- a/src/share/classes/java/util/HashMap.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/util/HashMap.java	Fri Jun 01 11:46:14 2012 -0700
@@ -146,7 +146,7 @@
     /**
      * The table, resized as necessary. Length MUST Always be a power of two.
      */
-    transient Entry[] table;
+    transient Entry<K,V>[] table;
 
     /**
      * The number of key-value mappings contained in this map.
@@ -176,6 +176,86 @@
     transient int modCount;
 
     /**
+     * The default threshold of capacity above which alternate hashing is used.
+     * Alternative hashing reduces the incidence of collisions due to weak hash
+     * code calculation.
+     * <p/>
+     * This value may be overridden by defining the system property
+     * {@code java.util.althashing.threshold}. A property value of {@code 1}
+     * forces alternative hashing to be used at all times whereas
+     * {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures that
+     * alternative hashing is never used.
+     */
+    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 0;
+
+    /**
+     * holds values which can't be initialized until after VM is booted.
+     */
+    private static class Holder {
+
+            // Unsafe mechanics
+        /**
+         *
+         */
+        static final sun.misc.Unsafe UNSAFE;
+
+        /**
+         * Offset of "final" hashmask field we must set in
+         * readObject() method.
+         */
+        static final long HASHSEED_OFFSET;
+
+        /**
+         * Table capacity above which to switch to use alternate hashing.
+         */
+        static final int ALTERNATE_HASHING_THRESHOLD;
+
+        static {
+            String altThreshold = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction(
+                    "jdk.map.althashing.threshold"));
+
+            int threshold;
+            try {
+                threshold = (null != altThreshold)
+                        ? Integer.parseInt(altThreshold)
+                        : ALTERNATE_HASHING_THRESHOLD_DEFAULT;
+
+                if(threshold == -1) {
+                    threshold = Integer.MAX_VALUE;
+                }
+
+                if(threshold < 0) {
+                    throw new IllegalArgumentException("value must be positive integer.");
+                }
+            } catch(IllegalArgumentException failed) {
+                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
+            }
+            ALTERNATE_HASHING_THRESHOLD = threshold;
+
+            try {
+                UNSAFE = sun.misc.Unsafe.getUnsafe();
+                HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
+                    HashMap.class.getDeclaredField("hashSeed"));
+            } catch (NoSuchFieldException | SecurityException e) {
+                throw new Error("Failed to record hashSeed offset", e);
+            }
+        }
+    }
+
+    /**
+     * If {@code true} then perform alternate hashing to reduce the incidence of
+     * collisions due to weak hash code calculation.
+     */
+    transient boolean useAltHashing;
+
+    /**
+     * A randomizing value associated with this instance that is applied to
+     * hash code of keys to make hash collisions harder to find.
+     */
+    transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
+
+    /**
      * Constructs an empty <tt>HashMap</tt> with the specified initial
      * capacity and load factor.
      *
@@ -200,8 +280,10 @@
             capacity <<= 1;
 
         this.loadFactor = loadFactor;
-        threshold = (int)(capacity * loadFactor);
+        threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
         table = new Entry[capacity];
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
         init();
     }
 
@@ -221,10 +303,7 @@
      * (16) and the default load factor (0.75).
      */
     public HashMap() {
-        this.loadFactor = DEFAULT_LOAD_FACTOR;
-        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
-        table = new Entry[DEFAULT_INITIAL_CAPACITY];
-        init();
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
     }
 
     /**
@@ -255,13 +334,23 @@
     }
 
     /**
-     * Applies a supplemental hash function to a given hashCode, which
-     * defends against poor quality hash functions.  This is critical
-     * because HashMap uses power-of-two length hash tables, that
+     * Retrieve object hash code and applies a supplemental hash function to the
+     * result hash, which defends against poor quality hash functions.  This is
+     * critical because HashMap uses power-of-two length hash tables, that
      * otherwise encounter collisions for hashCodes that do not differ
      * in lower bits. Note: Null keys always map to hash 0, thus index 0.
      */
-    static int hash(int h) {
+    final int hash(Object k) {
+        int h = 0;
+        if (useAltHashing) {
+            if (k instanceof String) {
+                return sun.misc.Hashing.stringHash32((String) k);
+            }
+            h = hashSeed;
+        }
+
+        h ^= k.hashCode();
+
         // This function ensures that hashCodes that differ only by
         // constant multiples at each bit position have a bounded
         // number of collisions (approximately 8 at default load factor).
@@ -314,15 +403,9 @@
     public V get(Object key) {
         if (key == null)
             return getForNullKey();
-        int hash = hash(key.hashCode());
-        for (Entry<K,V> e = table[indexFor(hash, table.length)];
-             e != null;
-             e = e.next) {
-            Object k;
-            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
-                return e.value;
-        }
-        return null;
+        Entry<K,V> entry = getEntry(key);
+
+        return null == entry ? null : entry.getValue();
     }
 
     /**
@@ -358,7 +441,7 @@
      * for the key.
      */
     final Entry<K,V> getEntry(Object key) {
-        int hash = (key == null) ? 0 : hash(key.hashCode());
+        int hash = (key == null) ? 0 : hash(key);
         for (Entry<K,V> e = table[indexFor(hash, table.length)];
              e != null;
              e = e.next) {
@@ -386,7 +469,7 @@
     public V put(K key, V value) {
         if (key == null)
             return putForNullKey(value);
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         int i = indexFor(hash, table.length);
         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
             Object k;
@@ -427,7 +510,7 @@
      * addEntry.
      */
     private void putForCreate(K key, V value) {
-        int hash = (key == null) ? 0 : hash(key.hashCode());
+        int hash = null == key ? 0 : hash(key);
         int i = indexFor(hash, table.length);
 
         /**
@@ -475,28 +558,30 @@
         }
 
         Entry[] newTable = new Entry[newCapacity];
-        transfer(newTable);
+        boolean oldAltHashing = useAltHashing;
+        useAltHashing |= sun.misc.VM.isBooted() &&
+                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+        boolean rehash = oldAltHashing ^ useAltHashing;
+        transfer(newTable, rehash);
         table = newTable;
-        threshold = (int)(newCapacity * loadFactor);
+        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
     }
 
     /**
      * Transfers all entries from current table to newTable.
      */
-    void transfer(Entry[] newTable) {
-        Entry[] src = table;
+    void transfer(Entry[] newTable, boolean rehash) {
         int newCapacity = newTable.length;
-        for (int j = 0; j < src.length; j++) {
-            Entry<K,V> e = src[j];
-            if (e != null) {
-                src[j] = null;
-                do {
-                    Entry<K,V> next = e.next;
-                    int i = indexFor(e.hash, newCapacity);
-                    e.next = newTable[i];
-                    newTable[i] = e;
-                    e = next;
-                } while (e != null);
+        for (Entry<K,V> e : table) {
+            while(null != e) {
+                Entry<K,V> next = e.next;
+                if(rehash) {
+                    e.hash = null == e.key ? 0 : hash(e.key);
+                }
+                int i = indexFor(e.hash, newCapacity);
+                e.next = newTable[i];
+                newTable[i] = e;
+                e = next;
             }
         }
     }
@@ -558,7 +643,7 @@
      * for this key.
      */
     final Entry<K,V> removeEntryForKey(Object key) {
-        int hash = (key == null) ? 0 : hash(key.hashCode());
+        int hash = (key == null) ? 0 : hash(key);
         int i = indexFor(hash, table.length);
         Entry<K,V> prev = table[i];
         Entry<K,V> e = prev;
@@ -585,7 +670,8 @@
     }
 
     /**
-     * Special version of remove for EntrySet.
+     * Special version of remove for EntrySet using {@code Map.Entry.equals()}
+     * for matching.
      */
     final Entry<K,V> removeMapping(Object o) {
         if (!(o instanceof Map.Entry))
@@ -688,7 +774,7 @@
         final K key;
         V value;
         Entry<K,V> next;
-        final int hash;
+        int hash;
 
         /**
          * Creates new entry.
@@ -762,10 +848,13 @@
      * Subclass overrides this to alter the behavior of put method.
      */
     void addEntry(int hash, K key, V value, int bucketIndex) {
-        Entry<K,V> e = table[bucketIndex];
-        table[bucketIndex] = new Entry<>(hash, key, value, e);
-        if (size++ >= threshold)
+        if ((size >= threshold) && (null != table[bucketIndex])) {
             resize(2 * table.length);
+            hash = (null != key) ? hash(key) : 0;
+            bucketIndex = indexFor(hash, table.length);
+        }
+
+        createEntry(hash, key, value, bucketIndex);
     }
 
     /**
@@ -827,7 +916,6 @@
             HashMap.this.removeEntryForKey(k);
             expectedModCount = modCount;
         }
-
     }
 
     private final class ValueIterator extends HashIterator<V> {
@@ -1007,9 +1095,8 @@
         s.writeInt(size);
 
         // Write out keys and values (alternating)
-        if (i != null) {
-            while (i.hasNext()) {
-                Map.Entry<K,V> e = i.next();
+        if (size > 0) {
+            for(Map.Entry<K,V> e : entrySet0()) {
                 s.writeObject(e.getKey());
                 s.writeObject(e.getValue());
             }
@@ -1019,26 +1106,52 @@
     private static final long serialVersionUID = 362498820763181265L;
 
     /**
-     * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
+     * Reconstitute the {@code HashMap} instance from a stream (i.e.,
      * deserialize it).
      */
     private void readObject(java.io.ObjectInputStream s)
          throws IOException, ClassNotFoundException
     {
-        // Read in the threshold, loadfactor, and any hidden stuff
+        // Read in the threshold (ignored), loadfactor, and any hidden stuff
         s.defaultReadObject();
+        if (loadFactor <= 0 || Float.isNaN(loadFactor))
+            throw new InvalidObjectException("Illegal load factor: " +
+                                               loadFactor);
+
+        // set hashSeed (can only happen after VM boot)
+        Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
+                sun.misc.Hashing.randomHashSeed(this));
 
         // Read in number of buckets and allocate the bucket array;
-        int numBuckets = s.readInt();
-        table = new Entry[numBuckets];
+        s.readInt(); // ignored
+
+        // Read number of mappings
+        int mappings = s.readInt();
+        if (mappings < 0)
+            throw new InvalidObjectException("Illegal mappings count: " +
+                                               mappings);
+
+        int initialCapacity = (int) Math.min(
+                // capacity chosen by number of mappings
+                // and desired load (if >= 0.25)
+                mappings * Math.min(1 / loadFactor, 4.0f),
+                // we have limits...
+                HashMap.MAXIMUM_CAPACITY);
+        int capacity = 1;
+        // find smallest power of two which holds all mappings
+        while (capacity < initialCapacity) {
+            capacity <<= 1;
+        }
+
+        table = new Entry[capacity];
+        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
 
         init();  // Give subclass a chance to do its thing.
 
-        // Read in size (number of Mappings)
-        int size = s.readInt();
-
         // Read the keys and values, and put the mappings in the HashMap
-        for (int i=0; i<size; i++) {
+        for (int i=0; i<mappings; i++) {
             K key = (K) s.readObject();
             V value = (V) s.readObject();
             putForCreate(key, value);
--- a/src/share/classes/java/util/Hashtable.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/util/Hashtable.java	Fri Jun 01 11:46:14 2012 -0700
@@ -129,7 +129,7 @@
     /**
      * The hash table data.
      */
-    private transient Entry[] table;
+    private transient Entry<K,V>[] table;
 
     /**
      * The total number of entries in the hash table.
@@ -164,6 +164,99 @@
     private static final long serialVersionUID = 1421746759512286392L;
 
     /**
+     * The default threshold of capacity above which alternate hashing is used.
+     * Alternative hashing reduces the incidence of collisions due to weak hash
+     * code calculation.
+     * <p/>
+     * This value may be overridden by defining the system property
+     * {@code java.util.althashing.threshold}. A property value of {@code 1}
+     * forces alternative hashing to be used at all times whereas
+     * {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures that
+     * alternative hashing is never used.
+     */
+    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 0;
+
+    /**
+     * holds values which can't be initialized until after VM is booted.
+     */
+    private static class Holder {
+
+        /**
+         * Table capacity above which to switch to use alternate hashing.
+         */
+        static final int ALTERNATE_HASHING_THRESHOLD;
+
+        static {
+            String altThreshold = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction(
+                    "jdk.map.althashing.threshold"));
+
+            int threshold;
+            try {
+                threshold = (null != altThreshold)
+                        ? Integer.parseInt(altThreshold)
+                        : 1;
+
+                if(threshold == -1) {
+                    threshold = Integer.MAX_VALUE;
+                }
+
+                if(threshold < 0) {
+                    throw new IllegalArgumentException("value must be positive integer.");
+                }
+            } catch(IllegalArgumentException failed) {
+                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
+            }
+
+            ALTERNATE_HASHING_THRESHOLD = threshold;
+        }
+    }
+
+    /**
+     * If {@code true} then perform alternate hashing to reduce the incidence of
+     * collisions due to weak hash code calculation.
+     */
+    transient boolean useAltHashing;
+
+    // Unsafe mechanics
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long HASHSEED_OFFSET;
+
+     static {
+        try {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
+                Hashtable.class.getDeclaredField("hashSeed"));
+        } catch (NoSuchFieldException | SecurityException e) {
+            throw new Error("Failed to record hashSeed offset", e);
+        }
+     }
+
+    /**
+     * A randomizing value associated with this instance that is applied to
+     * hash code of keys to make hash collisions harder to find.
+     */
+    transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
+
+    private int hash(Object k) {
+        if (useAltHashing) {
+            if (k.getClass() == String.class) {
+                return sun.misc.Hashing.stringHash32((String) k);
+            } else {
+                int h = hashSeed ^ k.hashCode();
+
+                // This function ensures that hashCodes that differ only by
+                // constant multiples at each bit position have a bounded
+                // number of collisions (approximately 8 at default load factor).
+                h ^= (h >>> 20) ^ (h >>> 12);
+                return h ^ (h >>> 7) ^ (h >>> 4);
+             }
+        } else  {
+            return k.hashCode();
+        }
+    }
+
+    /**
      * Constructs a new, empty hashtable with the specified initial
      * capacity and the specified load factor.
      *
@@ -183,7 +276,9 @@
             initialCapacity = 1;
         this.loadFactor = loadFactor;
         table = new Entry[initialCapacity];
-        threshold = (int)(initialCapacity * loadFactor);
+        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (initialCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
     }
 
     /**
@@ -327,7 +422,7 @@
      */
     public synchronized boolean containsKey(Object key) {
         Entry tab[] = table;
-        int hash = key.hashCode();
+        int hash = hash(key);
         int index = (hash & 0x7FFFFFFF) % tab.length;
         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
             if ((e.hash == hash) && e.key.equals(key)) {
@@ -354,7 +449,7 @@
      */
     public synchronized V get(Object key) {
         Entry tab[] = table;
-        int hash = key.hashCode();
+        int hash = hash(key);
         int index = (hash & 0x7FFFFFFF) % tab.length;
         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
             if ((e.hash == hash) && e.key.equals(key)) {
@@ -381,7 +476,7 @@
      */
     protected void rehash() {
         int oldCapacity = table.length;
-        Entry[] oldMap = table;
+        Entry<K,V>[] oldMap = table;
 
         // overflow-conscious code
         int newCapacity = (oldCapacity << 1) + 1;
@@ -391,10 +486,15 @@
                 return;
             newCapacity = MAX_ARRAY_SIZE;
         }
-        Entry[] newMap = new Entry[newCapacity];
+        Entry<K,V>[] newMap = new Entry[newCapacity];
 
         modCount++;
-        threshold = (int)(newCapacity * loadFactor);
+        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
+        boolean currentAltHashing = useAltHashing;
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+        boolean rehash = currentAltHashing ^ useAltHashing;
+
         table = newMap;
 
         for (int i = oldCapacity ; i-- > 0 ;) {
@@ -402,6 +502,9 @@
                 Entry<K,V> e = old;
                 old = old.next;
 
+                if(rehash) {
+                    e.hash = hash(e.key);
+                }
                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                 e.next = newMap[index];
                 newMap[index] = e;
@@ -434,7 +537,7 @@
 
         // Makes sure the key is not already in the hashtable.
         Entry tab[] = table;
-        int hash = key.hashCode();
+        int hash = hash(key);
         int index = (hash & 0x7FFFFFFF) % tab.length;
         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
             if ((e.hash == hash) && e.key.equals(key)) {
@@ -450,6 +553,7 @@
             rehash();
 
             tab = table;
+            hash = hash(key);
             index = (hash & 0x7FFFFFFF) % tab.length;
         }
 
@@ -471,7 +575,7 @@
      */
     public synchronized V remove(Object key) {
         Entry tab[] = table;
-        int hash = key.hashCode();
+        int hash = hash(key);
         int index = (hash & 0x7FFFFFFF) % tab.length;
         for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
             if ((e.hash == hash) && e.key.equals(key)) {
@@ -678,7 +782,7 @@
             Map.Entry entry = (Map.Entry)o;
             Object key = entry.getKey();
             Entry[] tab = table;
-            int hash = key.hashCode();
+            int hash = hash(key);
             int index = (hash & 0x7FFFFFFF) % tab.length;
 
             for (Entry e = tab[index]; e != null; e = e.next)
@@ -693,7 +797,7 @@
             Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
             K key = entry.getKey();
             Entry[] tab = table;
-            int hash = key.hashCode();
+            int hash = hash(key);
             int index = (hash & 0x7FFFFFFF) % tab.length;
 
             for (Entry<K,V> e = tab[index], prev = null; e != null;
@@ -827,9 +931,11 @@
 
         loadFactor = -loadFactor;  // Mark hashCode computation in progress
         Entry[] tab = table;
-        for (int i = 0; i < tab.length; i++)
-            for (Entry e = tab[i]; e != null; e = e.next)
-                h += e.key.hashCode() ^ e.value.hashCode();
+        for (Entry<K,V> entry : tab)
+            while (entry != null) {
+                h += entry.hashCode();
+                entry = entry.next;
+            }
         loadFactor = -loadFactor;  // Mark hashCode computation complete
 
         return h;
@@ -847,7 +953,7 @@
      */
     private void writeObject(java.io.ObjectOutputStream s)
             throws IOException {
-        Entry<Object, Object> entryStack = null;
+        Entry<K, V> entryStack = null;
 
         synchronized (this) {
             // Write out the length, threshold, loadfactor
@@ -859,7 +965,7 @@
 
             // Stack copies of the entries in the table
             for (int index = 0; index < table.length; index++) {
-                Entry entry = table[index];
+                Entry<K,V> entry = table[index];
 
                 while (entry != null) {
                     entryStack =
@@ -886,6 +992,10 @@
         // Read in the length, threshold, and loadfactor
         s.defaultReadObject();
 
+        // set hashSeed
+        UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
+                sun.misc.Hashing.randomHashSeed(this));
+
         // Read the original length of the array and number of elements
         int origlength = s.readInt();
         int elements = s.readInt();
@@ -900,8 +1010,11 @@
         if (origlength > 0 && length > origlength)
             length = origlength;
 
-        Entry[] table = new Entry[length];
+        Entry<K,V>[] table = new Entry[length];
+        threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
         count = 0;
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (length >= Holder.ALTERNATE_HASHING_THRESHOLD);
 
         // Read the number of elements and then all the key/value objects
         for (; elements > 0; elements--) {
@@ -924,7 +1037,7 @@
      * because we are creating a new instance. Also, no return value
      * is needed.
      */
-    private void reconstitutionPut(Entry[] tab, K key, V value)
+    private void reconstitutionPut(Entry<K,V>[] tab, K key, V value)
         throws StreamCorruptedException
     {
         if (value == null) {
@@ -932,7 +1045,7 @@
         }
         // Makes sure the key is not already in the hashtable.
         // This should not happen in deserialized version.
-        int hash = key.hashCode();
+        int hash = hash(key);
         int index = (hash & 0x7FFFFFFF) % tab.length;
         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
             if ((e.hash == hash) && e.key.equals(key)) {
@@ -946,7 +1059,7 @@
     }
 
     /**
-     * Hashtable collision list.
+     * Hashtable bucket collision list entry
      */
     private static class Entry<K,V> implements Map.Entry<K,V> {
         int hash;
@@ -956,7 +1069,7 @@
 
         protected Entry(int hash, K key, V value, Entry<K,V> next) {
             this.hash = hash;
-            this.key = key;
+            this.key =  key;
             this.value = value;
             this.next = next;
         }
@@ -988,14 +1101,13 @@
         public boolean equals(Object o) {
             if (!(o instanceof Map.Entry))
                 return false;
-            Map.Entry e = (Map.Entry)o;
+            Map.Entry<?,?> e = (Map.Entry)o;
 
-            return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
-               (value==null ? e.getValue()==null : value.equals(e.getValue()));
+            return key.equals(e.getKey()) && value.equals(e.getValue());
         }
 
         public int hashCode() {
-            return hash ^ (value==null ? 0 : value.hashCode());
+            return hash ^ value.hashCode();
         }
 
         public String toString() {
--- a/src/share/classes/java/util/LinkedHashMap.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/util/LinkedHashMap.java	Fri Jun 01 11:46:14 2012 -0700
@@ -236,6 +236,7 @@
      * readObject) before any entries are inserted into the map.  Initializes
      * the chain.
      */
+    @Override
     void init() {
         header = new Entry<>(-1, null, null, null);
         header.before = header.after = header;
@@ -246,9 +247,12 @@
      * by superclass resize.  It is overridden for performance, as it is
      * faster to iterate using our linked list.
      */
-    void transfer(HashMap.Entry[] newTable) {
+    @Override
+    void transfer(HashMap.Entry[] newTable, boolean rehash) {
         int newCapacity = newTable.length;
         for (Entry<K,V> e = header.after; e != header; e = e.after) {
+            if (rehash)
+                e.hash = (e.key == null) ? 0 : hash(e.key);
             int index = indexFor(e.hash, newCapacity);
             e.next = newTable[index];
             newTable[index] = e;
@@ -420,15 +424,12 @@
      * removes the eldest entry if appropriate.
      */
     void addEntry(int hash, K key, V value, int bucketIndex) {
-        createEntry(hash, key, value, bucketIndex);
+        super.addEntry(hash, key, value, bucketIndex);
 
-        // Remove eldest entry if instructed, else grow capacity if appropriate
+        // Remove eldest entry if instructed
         Entry<K,V> eldest = header.after;
         if (removeEldestEntry(eldest)) {
             removeEntryForKey(eldest.key);
-        } else {
-            if (size >= threshold)
-                resize(2 * table.length);
         }
     }
 
--- a/src/share/classes/java/util/WeakHashMap.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/util/WeakHashMap.java	Fri Jun 01 11:46:14 2012 -0700
@@ -184,6 +184,66 @@
      */
     int modCount;
 
+    /**
+    * The default threshold of capacity above which alternate hashing is
+    * used. Alternative hashing reduces the incidence of collisions due to
+    * weak hash code calculation.
+    * <p/>
+    * This value may be overridden by defining the system property
+    * {@code java.util.althashing.threshold} to an integer value. A property
+    * value of {@code 1} forces alternative hashing to be used at all times
+    * whereas {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures
+    * that alternative hashing is never used.
+    */
+    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 0;
+
+    /**
+     * holds values which can't be initialized until after VM is booted.
+     */
+    private static class Holder {
+
+        /**
+         * Table capacity above which to switch to use alternate hashing.
+         */
+        static final int ALTERNATE_HASHING_THRESHOLD;
+
+        static {
+            String altThreshold = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction(
+                    "jdk.map.althashing.threshold"));
+
+            int threshold;
+            try {
+                threshold = (null != altThreshold)
+                        ? Integer.parseInt(altThreshold)
+                        : ALTERNATE_HASHING_THRESHOLD_DEFAULT;
+
+                if(threshold == -1) {
+                    threshold = Integer.MAX_VALUE;
+                }
+
+                if(threshold < 0) {
+                    throw new IllegalArgumentException("value must be positive integer.");
+                }
+            } catch(IllegalArgumentException failed) {
+                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
+            }
+            ALTERNATE_HASHING_THRESHOLD = threshold;
+        }
+    }
+
+    /**
+     * If {@code true} then perform alternate hashing to reduce the incidence of
+     * collisions due to weak hash code calculation.
+     */
+    transient boolean useAltHashing;
+
+    /**
+     * A randomizing value associated with this instance that is applied to
+     * hash code of keys to make hash collisions harder to find.
+     */
+    transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
+
     @SuppressWarnings("unchecked")
     private Entry<K,V>[] newTable(int n) {
         return (Entry<K,V>[]) new Entry[n];
@@ -214,6 +274,8 @@
         table = newTable(capacity);
         this.loadFactor = loadFactor;
         threshold = (int)(capacity * loadFactor);
+        useAltHashing = sun.misc.VM.isBooted() &&
+                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
     }
 
     /**
@@ -232,9 +294,7 @@
      * capacity (16) and load factor (0.75).
      */
     public WeakHashMap() {
-        this.loadFactor = DEFAULT_LOAD_FACTOR;
-        threshold = DEFAULT_INITIAL_CAPACITY;
-        table = newTable(DEFAULT_INITIAL_CAPACITY);
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
     }
 
     /**
@@ -248,7 +308,8 @@
      * @since   1.3
      */
     public WeakHashMap(Map<? extends K, ? extends V> m) {
-        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 16),
+        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
+                DEFAULT_INITIAL_CAPACITY),
              DEFAULT_LOAD_FACTOR);
         putAll(m);
     }
@@ -283,6 +344,34 @@
     }
 
     /**
+     * Retrieve object hash code and applies a supplemental hash function to the
+     * result hash, which defends against poor quality hash functions.  This is
+     * critical because HashMap uses power-of-two length hash tables, that
+     * otherwise encounter collisions for hashCodes that do not differ
+     * in lower bits.
+     */
+    int hash(Object k) {
+
+        int h;
+        if (useAltHashing) {
+            h = hashSeed;
+            if (k instanceof String) {
+                return h ^ sun.misc.Hashing.stringHash32((String) k);
+            } else {
+                h ^= k.hashCode();
+            }
+        } else  {
+            h = k.hashCode();
+        }
+
+        // This function ensures that hashCodes that differ only by
+        // constant multiples at each bit position have a bounded
+        // number of collisions (approximately 8 at default load factor).
+        h ^= (h >>> 20) ^ (h >>> 12);
+        return h ^ (h >>> 7) ^ (h >>> 4);
+    }
+
+    /**
      * Returns index for hash code h.
      */
     private static int indexFor(int h, int length) {
@@ -371,7 +460,7 @@
      */
     public V get(Object key) {
         Object k = maskNull(key);
-        int h = HashMap.hash(k.hashCode());
+        int h = hash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -401,7 +490,7 @@
      */
     Entry<K,V> getEntry(Object key) {
         Object k = maskNull(key);
-        int h = HashMap.hash(k.hashCode());
+        int h = hash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -424,7 +513,7 @@
      */
     public V put(K key, V value) {
         Object k = maskNull(key);
-        int h = HashMap.hash(k.hashCode());
+        int h = hash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
 
@@ -468,7 +557,11 @@
         }
 
         Entry<K,V>[] newTable = newTable(newCapacity);
-        transfer(oldTable, newTable);
+        boolean oldAltHashing = useAltHashing;
+        useAltHashing |= sun.misc.VM.isBooted() &&
+                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+        boolean rehash = oldAltHashing ^ useAltHashing;
+        transfer(oldTable, newTable, rehash);
         table = newTable;
 
         /*
@@ -480,13 +573,13 @@
             threshold = (int)(newCapacity * loadFactor);
         } else {
             expungeStaleEntries();
-            transfer(newTable, oldTable);
+            transfer(newTable, oldTable, false);
             table = oldTable;
         }
     }
 
     /** Transfers all entries from src to dest tables */
-    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
+    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest, boolean rehash) {
         for (int j = 0; j < src.length; ++j) {
             Entry<K,V> e = src[j];
             src[j] = null;
@@ -498,6 +591,9 @@
                     e.value = null; //  "   "
                     size--;
                 } else {
+                    if(rehash) {
+                        e.hash = hash(key);
+                    }
                     int i = indexFor(e.hash, dest.length);
                     e.next = dest[i];
                     dest[i] = e;
@@ -566,7 +662,7 @@
      */
     public V remove(Object key) {
         Object k = maskNull(key);
-        int h = HashMap.hash(k.hashCode());
+        int h = hash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
@@ -597,7 +693,7 @@
         Entry<K,V>[] tab = getTable();
         Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
         Object k = maskNull(entry.getKey());
-        int h = HashMap.hash(k.hashCode());
+        int h = hash(k);
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
         Entry<K,V> e = prev;
@@ -679,7 +775,7 @@
      */
     private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
         V value;
-        final int hash;
+        int hash;
         Entry<K,V> next;
 
         /**
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Jun 01 11:46:14 2012 -0700
@@ -178,6 +178,55 @@
     /* ---------------- Fields -------------- */
 
     /**
+     * holds values which can't be initialized until after VM is booted.
+     */
+    private static class Holder {
+
+        /**
+        * Enable alternate hashing?
+        */
+        static final boolean ALTERNATE_HASHING;
+
+        static {
+            String altThreshold = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction(
+                    "jdk.map.althashing.threshold"));
+
+            int threshold;
+            try {
+                threshold = (null != altThreshold)
+                        ? Integer.parseInt(altThreshold)
+                        : 1;
+
+                if(threshold == -1) {
+                    threshold = Integer.MAX_VALUE;
+                }
+
+                if(threshold < 0) {
+                    throw new IllegalArgumentException("value must be positive integer.");
+                }
+            } catch(IllegalArgumentException failed) {
+                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
+            }
+            ALTERNATE_HASHING = threshold <= MAXIMUM_CAPACITY;
+        }
+    }
+
+    /**
+     * A randomizing value associated with this instance that is applied to
+     * hash code of keys to make hash collisions harder to find.
+     */
+    private transient final int hashSeed = randomHashSeed(this);
+
+    private static int randomHashSeed(ConcurrentHashMap instance) {
+        if (sun.misc.VM.isBooted() && Holder.ALTERNATE_HASHING) {
+            return sun.misc.Hashing.randomHashSeed(instance);
+        }
+
+        return 0;
+    }
+
+    /**
      * Mask value for indexing into segments. The upper bits of a
      * key's hash code are used to choose the segment.
      */
@@ -265,7 +314,15 @@
      * that otherwise encounter collisions for hashCodes that do not
      * differ in lower or upper bits.
      */
-    private static int hash(int h) {
+    private int hash(Object k) {
+        int h = hashSeed;
+
+        if ((0 != h) && (k instanceof String)) {
+            return sun.misc.Hashing.stringHash32((String) k);
+        }
+
+        h ^= k.hashCode();
+
         // Spread bits to regularize both segment and index locations,
         // using variant of single-word Wang/Jenkins hash.
         h += (h <<  15) ^ 0xffffcd7d;
@@ -919,7 +976,7 @@
     public V get(Object key) {
         Segment<K,V> s; // manually integrate access methods to reduce overhead
         HashEntry<K,V>[] tab;
-        int h = hash(key.hashCode());
+        int h = hash(key);
         long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
         if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
             (tab = s.table) != null) {
@@ -947,7 +1004,7 @@
     public boolean containsKey(Object key) {
         Segment<K,V> s; // same as get() except no need for volatile value read
         HashEntry<K,V>[] tab;
-        int h = hash(key.hashCode());
+        int h = hash(key);
         long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
         if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
             (tab = s.table) != null) {
@@ -1056,7 +1113,7 @@
         Segment<K,V> s;
         if (value == null)
             throw new NullPointerException();
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         int j = (hash >>> segmentShift) & segmentMask;
         if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
              (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
@@ -1076,7 +1133,7 @@
         Segment<K,V> s;
         if (value == null)
             throw new NullPointerException();
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         int j = (hash >>> segmentShift) & segmentMask;
         if ((s = (Segment<K,V>)UNSAFE.getObject
              (segments, (j << SSHIFT) + SBASE)) == null)
@@ -1106,7 +1163,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public V remove(Object key) {
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         Segment<K,V> s = segmentForHash(hash);
         return s == null ? null : s.remove(key, hash, null);
     }
@@ -1117,7 +1174,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public boolean remove(Object key, Object value) {
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         Segment<K,V> s;
         return value != null && (s = segmentForHash(hash)) != null &&
             s.remove(key, hash, value) != null;
@@ -1129,7 +1186,7 @@
      * @throws NullPointerException if any of the arguments are null
      */
     public boolean replace(K key, V oldValue, V newValue) {
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         if (oldValue == null || newValue == null)
             throw new NullPointerException();
         Segment<K,V> s = segmentForHash(hash);
@@ -1144,7 +1201,7 @@
      * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
-        int hash = hash(key.hashCode());
+        int hash = hash(key);
         if (value == null)
             throw new NullPointerException();
         Segment<K,V> s = segmentForHash(hash);
@@ -1472,6 +1529,9 @@
         throws IOException, ClassNotFoundException {
         s.defaultReadObject();
 
+        // set hashMask
+        UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, randomHashSeed(this));
+
         // Re-initialize segments to be minimally sized, and let grow.
         int cap = MIN_SEGMENT_TABLE_CAPACITY;
         final Segment<K,V>[] segments = this.segments;
@@ -1499,6 +1559,7 @@
     private static final int SSHIFT;
     private static final long TBASE;
     private static final int TSHIFT;
+    private static final long HASHSEED_OFFSET;
 
     static {
         int ss, ts;
@@ -1510,6 +1571,8 @@
             SBASE = UNSAFE.arrayBaseOffset(sc);
             ts = UNSAFE.arrayIndexScale(tc);
             ss = UNSAFE.arrayIndexScale(sc);
+            HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
+                ConcurrentHashMap.class.getDeclaredField("hashSeed"));
         } catch (Exception e) {
             throw new Error(e);
         }
--- a/src/share/classes/sun/awt/FontConfiguration.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/sun/awt/FontConfiguration.java	Fri Jun 01 11:46:14 2012 -0700
@@ -947,7 +947,7 @@
                     public Object run() {
                         try {
                             return Class.forName(charsetName, true,
-                                                 Thread.currentThread().getContextClassLoader());
+                                                 ClassLoader.getSystemClassLoader());
                         } catch (ClassNotFoundException e) {
                         }
                         return null;
--- a/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java	Fri Jun 01 11:46:14 2012 -0700
@@ -498,7 +498,7 @@
         postDropTargetEvent(component, x, y, dropAction, actions,
                             formats, nativeCtxt,
                             SunDropTargetEvent.MOUSE_DROPPED,
-                            !SunDropTargetContextPeer.DISPATCH_SYNC);
+                            SunDropTargetContextPeer.DISPATCH_SYNC);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/Hashing.java	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.misc;
+
+import java.util.Random;
+
+/**
+ * Hashing utilities.
+ *
+ * Little endian implementations of Murmur3 hashing.
+ */
+public class Hashing {
+
+    /**
+     * Static utility methods only.
+     */
+    private Hashing() {
+        throw new Error("No instances");
+    }
+
+    public static int murmur3_32(byte[] data) {
+        return murmur3_32(0, data, 0, data.length);
+    }
+
+    public static int murmur3_32(int seed, byte[] data) {
+        return murmur3_32(seed, data, 0, data.length);
+    }
+
+    @SuppressWarnings("fallthrough")
+    public static int murmur3_32(int seed, byte[] data, int offset, int len) {
+        int h1 = seed;
+        int count = len;
+
+        // body
+        while (count >= 4) {
+            int k1 = (data[offset] & 0x0FF)
+                    | (data[offset + 1] & 0x0FF) << 8
+                    | (data[offset + 2] & 0x0FF) << 16
+                    | data[offset + 3] << 24;
+
+            count -= 4;
+            offset += 4;
+
+            k1 *= 0xcc9e2d51;
+            k1 = Integer.rotateLeft(k1, 15);
+            k1 *= 0x1b873593;
+
+            h1 ^= k1;
+            h1 = Integer.rotateLeft(h1, 13);
+            h1 = h1 * 5 + 0xe6546b64;
+        }
+
+        // tail
+
+        if (count > 0) {
+            int k1 = 0;
+
+            switch (count) {
+                case 3:
+                    k1 ^= (data[offset + 2] & 0xff) << 16;
+                // fall through
+                case 2:
+                    k1 ^= (data[offset + 1] & 0xff) << 8;
+                // fall through
+                case 1:
+                    k1 ^= (data[offset] & 0xff);
+                // fall through
+                default:
+                    k1 *= 0xcc9e2d51;
+                    k1 = Integer.rotateLeft(k1, 15);
+                    k1 *= 0x1b873593;
+                    h1 ^= k1;
+            }
+        }
+
+        // finalization
+
+        h1 ^= len;
+
+        // finalization mix force all bits of a hash block to avalanche
+        h1 ^= h1 >>> 16;
+        h1 *= 0x85ebca6b;
+        h1 ^= h1 >>> 13;
+        h1 *= 0xc2b2ae35;
+        h1 ^= h1 >>> 16;
+
+        return h1;
+    }
+
+    public static int murmur3_32(char[] data) {
+        return murmur3_32(0, data, 0, data.length);
+    }
+
+    public static int murmur3_32(int seed, char[] data) {
+        return murmur3_32(seed, data, 0, data.length);
+    }
+
+    public static int murmur3_32(int seed, char[] data, int offset, int len) {
+        int h1 = seed;
+
+        int off = offset;
+        int count = len;
+
+        // body
+        while (count >= 2) {
+            int k1 = (data[off++] & 0xFFFF) | (data[off++] << 16);
+
+            count -= 2;
+
+            k1 *= 0xcc9e2d51;
+            k1 = Integer.rotateLeft(k1, 15);
+            k1 *= 0x1b873593;
+
+            h1 ^= k1;
+            h1 = Integer.rotateLeft(h1, 13);
+            h1 = h1 * 5 + 0xe6546b64;
+        }
+
+        // tail
+
+        if (count > 0) {
+            int k1 = data[off];
+
+            k1 *= 0xcc9e2d51;
+            k1 = Integer.rotateLeft(k1, 15);
+            k1 *= 0x1b873593;
+            h1 ^= k1;
+        }
+
+        // finalization
+
+        h1 ^= len * (Character.SIZE / Byte.SIZE);
+
+        // finalization mix force all bits of a hash block to avalanche
+        h1 ^= h1 >>> 16;
+        h1 *= 0x85ebca6b;
+        h1 ^= h1 >>> 13;
+        h1 *= 0xc2b2ae35;
+        h1 ^= h1 >>> 16;
+
+        return h1;
+    }
+
+    public static int murmur3_32(int[] data) {
+        return murmur3_32(0, data, 0, data.length);
+    }
+
+    public static int murmur3_32(int seed, int[] data) {
+        return murmur3_32(seed, data, 0, data.length);
+    }
+
+    public static int murmur3_32(int seed, int[] data, int offset, int len) {
+        int h1 = seed;
+
+        int off = offset;
+        int end = offset + len;
+
+        // body
+        while (off < end) {
+            int k1 = data[off++];
+
+            k1 *= 0xcc9e2d51;
+            k1 = Integer.rotateLeft(k1, 15);
+            k1 *= 0x1b873593;
+
+            h1 ^= k1;
+            h1 = Integer.rotateLeft(h1, 13);
+            h1 = h1 * 5 + 0xe6546b64;
+        }
+
+        // tail (always empty, as body is always 32-bit chunks)
+
+        // finalization
+
+        h1 ^= len * (Integer.SIZE / Byte.SIZE);
+
+        // finalization mix force all bits of a hash block to avalanche
+        h1 ^= h1 >>> 16;
+        h1 *= 0x85ebca6b;
+        h1 ^= h1 >>> 13;
+        h1 *= 0xc2b2ae35;
+        h1 ^= h1 >>> 16;
+
+        return h1;
+    }
+
+    /**
+     * Holds references to things that can't be initialized until after VM
+     * is fully booted.
+     */
+    private static class Holder {
+
+        /**
+         * Used for generating per-instance hash seeds.
+         *
+         * We try to improve upon the default seeding.
+         */
+        static final Random SEED_MAKER = new Random(
+                Double.doubleToRawLongBits(Math.random())
+                ^ System.identityHashCode(Hashing.class)
+                ^ System.currentTimeMillis()
+                ^ System.nanoTime()
+                ^ Runtime.getRuntime().freeMemory());
+
+        /**
+         * Access to {@code String.hash32()}
+         */
+        static final JavaLangAccess LANG_ACCESS;
+
+        static {
+            LANG_ACCESS = SharedSecrets.getJavaLangAccess();
+            if (null == LANG_ACCESS) {
+                throw new Error("Shared secrets not initialized");
+            }
+        }
+    }
+
+    /**
+     * Return a 32 bit hash value for the specified string. The algorithm is
+     * unspecified but will be consistent within a VM instance.
+     *
+     * @param string String to be hashed.
+     * @return hash value of the string.
+     */
+    public static int stringHash32(String string) {
+        return Holder.LANG_ACCESS.getStringHash32(string);
+    }
+
+    public static int randomHashSeed(Object instance) {
+        int seed;
+        if (sun.misc.VM.isBooted()) {
+            seed = Holder.SEED_MAKER.nextInt();
+        } else {
+            // lower quality "random" seed value--still better than zero and not
+            // not practically reversible.
+            int hashing_seed[] = {
+                System.identityHashCode(Hashing.class),
+                System.identityHashCode(instance),
+                System.identityHashCode(Thread.currentThread()),
+                (int) Thread.currentThread().getId(),
+                (int) (System.currentTimeMillis() >>> 2), // resolution is poor
+                (int) (System.nanoTime() >>> 5), // resolution is poor
+                (int) (Runtime.getRuntime().freeMemory() >>> 4) // alloc min
+            };
+
+            seed = murmur3_32(hashing_seed);
+        }
+
+        // force to non-zero.
+        return (0 != seed) ? seed : 1;
+    }
+}
--- a/src/share/classes/sun/misc/JavaLangAccess.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/sun/misc/JavaLangAccess.java	Fri Jun 01 11:46:14 2012 -0700
@@ -83,4 +83,9 @@
      * Returns the ith StackTraceElement for the given throwable.
      */
     StackTraceElement getStackTraceElement(Throwable t, int i);
+
+    /**
+     * Returns the murmur hash value for the specified String.
+     */
+    int getStringHash32(String string);
 }
--- a/src/share/classes/sun/util/PreHashedMap.java	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/classes/sun/util/PreHashedMap.java	Fri Jun 01 11:46:14 2012 -0700
@@ -126,7 +126,7 @@
      */
     protected abstract void init(Object[] ht);
 
-    // @SuppressWarnings("unchecked")
+    @SuppressWarnings("unchecked")
     private V toV(Object x) {
         return (V)x;
     }
@@ -254,6 +254,7 @@
                                            ? 0
                                            : v.hashCode()));
                             }
+                            @SuppressWarnings("unchecked")
                             public boolean equals(Object ob) {
                                 if (ob == this)
                                     return true;
--- a/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c	Fri Jun 01 11:46:14 2012 -0700
@@ -89,6 +89,12 @@
                          (ci)->input_position <= (ci)->input_len && \
                          (ci)->output_position <= (ci)->output_len) )
 
+#define BUFSIZE 256
+
+#ifdef _WIN32
+#define snprintf(buffer, count, format, ...) _snprintf_s(buffer, count, _TRUNCATE, format, ##__VA_ARGS__)
+#endif
+
 /* Typedefs for various integral numbers, just for code clarity */
 
 typedef unsigned       ClassOpcode;             /* One opcode */
@@ -651,6 +657,7 @@
         unsigned int    index2;
         unsigned        len;
         char *          utf8;
+        char message[BUFSIZE];
 
         ipos    = i;
         index1  = 0;
@@ -689,8 +696,20 @@
                 utf8[len] = 0;
                 write_bytes(ci, (void*)utf8, len);
                 break;
+            case JVM_CONSTANT_MethodType:
+                index1 = copyU2(ci);
+                break;
+            case JVM_CONSTANT_MethodHandle:
+                index1 = copyU1(ci);
+                index2 = copyU2(ci);
+                break;
+            case JVM_CONSTANT_InvokeDynamic:
+                index1 = copyU2(ci);
+                index2 = copyU2(ci);
+                break;
             default:
-                CRW_FATAL(ci, "Unknown constant");
+                snprintf(message, BUFSIZE, "Unknown tag: %d, at ipos %hu", tag, ipos);
+                CRW_FATAL(ci, message);
                 break;
         }
         fillin_cpool_entry(ci, ipos, tag, index1, index2, (const char *)utf8, len);
--- a/src/share/javavm/export/classfile_constants.h	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/javavm/export/classfile_constants.h	Fri Jun 01 11:46:14 2012 -0700
@@ -86,7 +86,8 @@
     JVM_CONSTANT_InterfaceMethodref     = 11,
     JVM_CONSTANT_NameAndType            = 12,
     JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
-    JVM_CONSTANT_MethodType             = 16   // JSR 292
+    JVM_CONSTANT_MethodType             = 16,   // JSR 292
+    JVM_CONSTANT_InvokeDynamic          = 18
 };
 
 /* JVM_CONSTANT_MethodHandle subtypes */
--- a/src/share/native/sun/java2d/opengl/OGLContext.h	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/native/sun/java2d/opengl/OGLContext.h	Fri Jun 01 11:46:14 2012 -0700
@@ -84,6 +84,7 @@
     GLdouble   *xformMatrix;
     GLuint     blitTextureID;
     GLint      textureFunction;
+    jboolean   vertexCacheEnabled;
 } OGLContext;
 
 /**
--- a/src/share/native/sun/java2d/opengl/OGLTextRenderer.c	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/native/sun/java2d/opengl/OGLTextRenderer.c	Fri Jun 01 11:46:14 2012 -0700
@@ -202,11 +202,6 @@
 
     J2dTraceLn(J2D_TRACE_INFO, "OGLTR_InitGlyphCache");
 
-    // init vertex cache (if it hasn't been already)
-    if (!OGLVertexCache_InitVertexCache()) {
-        return JNI_FALSE;
-    }
-
     // init glyph cache data structure
     gcinfo = AccelGlyphCache_Init(OGLTR_CACHE_WIDTH,
                                   OGLTR_CACHE_HEIGHT,
@@ -583,6 +578,10 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "OGLTR_EnableGlyphVertexCache");
 
+    if (!OGLVertexCache_InitVertexCache(oglc)) {
+        return;
+    }
+
     if (glyphCache == NULL) {
         if (!OGLTR_InitGlyphCache(JNI_FALSE)) {
             return;
--- a/src/share/native/sun/java2d/opengl/OGLVertexCache.c	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/native/sun/java2d/opengl/OGLVertexCache.c	Fri Jun 01 11:46:14 2012 -0700
@@ -67,30 +67,32 @@
     } while (0)
 
 jboolean
-OGLVertexCache_InitVertexCache()
+OGLVertexCache_InitVertexCache(OGLContext *oglc)
 {
     J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_InitVertexCache");
 
-    if (vertexCache != NULL) {
-        return JNI_TRUE;
+    if (vertexCache == NULL) {
+        vertexCache = (J2DVertex *)malloc(OGLVC_MAX_INDEX * sizeof(J2DVertex));
+        if (vertexCache == NULL) {
+            return JNI_FALSE;
+        }
     }
 
-    vertexCache = (J2DVertex *)malloc(OGLVC_MAX_INDEX * sizeof(J2DVertex));
-    if (vertexCache == NULL) {
-        return JNI_FALSE;
+    if (!oglc->vertexCacheEnabled) {
+        j2d_glTexCoordPointer(2, GL_FLOAT,
+                              sizeof(J2DVertex), vertexCache);
+        j2d_glColorPointer(4, GL_UNSIGNED_BYTE,
+                           sizeof(J2DVertex), ((jfloat *)vertexCache) + 2);
+        j2d_glVertexPointer(2, GL_FLOAT,
+                            sizeof(J2DVertex), ((jfloat *)vertexCache) + 3);
+
+        j2d_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        j2d_glEnableClientState(GL_COLOR_ARRAY);
+        j2d_glEnableClientState(GL_VERTEX_ARRAY);
+
+        oglc->vertexCacheEnabled = JNI_TRUE;
     }
 
-    j2d_glTexCoordPointer(2, GL_FLOAT,
-                          sizeof(J2DVertex), vertexCache);
-    j2d_glColorPointer(4, GL_UNSIGNED_BYTE,
-                       sizeof(J2DVertex), ((jfloat *)vertexCache) + 2);
-    j2d_glVertexPointer(2, GL_FLOAT,
-                        sizeof(J2DVertex), ((jfloat *)vertexCache) + 3);
-
-    j2d_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    j2d_glEnableClientState(GL_COLOR_ARRAY);
-    j2d_glEnableClientState(GL_VERTEX_ARRAY);
-
     return JNI_TRUE;
 }
 
@@ -149,10 +151,6 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_InitMaskCache");
 
-    if (!OGLVertexCache_InitVertexCache()) {
-        return JNI_FALSE;
-    }
-
     maskCacheTexID =
         OGLContext_CreateBlitTexture(GL_INTENSITY8, GL_LUMINANCE,
                                      OGLVC_MASK_CACHE_WIDTH_IN_TEXELS,
@@ -179,6 +177,10 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_EnableMaskCache");
 
+    if (!OGLVertexCache_InitVertexCache(oglc)) {
+        return;
+    }
+
     if (maskCacheTexID == 0) {
         if (!OGLVertexCache_InitMaskCache()) {
             return;
--- a/src/share/native/sun/java2d/opengl/OGLVertexCache.h	Thu May 31 14:06:48 2012 -0700
+++ b/src/share/native/sun/java2d/opengl/OGLVertexCache.h	Fri Jun 01 11:46:14 2012 -0700
@@ -65,7 +65,7 @@
 /**
  * Exported methods.
  */
-jboolean OGLVertexCache_InitVertexCache();
+jboolean OGLVertexCache_InitVertexCache(OGLContext *oglc);
 void OGLVertexCache_FlushVertexCache();
 void OGLVertexCache_RestoreColorState(OGLContext *oglc);
 
--- a/src/windows/native/java/lang/java_props_md.c	Thu May 31 14:06:48 2012 -0700
+++ b/src/windows/native/java/lang/java_props_md.c	Fri Jun 01 11:46:14 2012 -0700
@@ -389,6 +389,7 @@
          * Windows Server 2008          6               0  (!VER_NT_WORKSTATION)
          * Windows 7                    6               1  (VER_NT_WORKSTATION)
          * Windows Server 2008 R2       6               1  (!VER_NT_WORKSTATION)
+         * Windows 8                    6               2  (VER_NT_WORKSTATION)
          *
          * This mapping will presumably be augmented as new Windows
          * versions are released.
@@ -445,6 +446,7 @@
                     switch (ver.dwMinorVersion) {
                     case  0: sprops.os_name = "Windows Vista";        break;
                     case  1: sprops.os_name = "Windows 7";            break;
+                    case  2: sprops.os_name = "Windows 8";            break;
                     default: sprops.os_name = "Windows NT (unknown)";
                     }
                 } else {
--- a/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c	Thu May 31 14:06:48 2012 -0700
+++ b/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c	Fri Jun 01 11:46:14 2012 -0700
@@ -466,7 +466,17 @@
         }
         CloseHandle(hThread);
     } else {
-        JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed");
+        if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
+            //
+            // This error will occur when attaching to a process belonging to
+            // another terminal session. See "Remarks":
+            // http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx
+            //
+            JNU_ThrowIOException(env,
+                "Insufficient memory or insufficient privileges to attach");
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed");
+        }
     }
 
     VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
--- a/test/java/awt/GraphicsDevice/CloneConfigsTest.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/awt/GraphicsDevice/CloneConfigsTest.java	Fri Jun 01 11:46:14 2012 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     6822057
+ * @bug     6822057 7124400
  *
  * @summary Test verifies that list of supported graphics configurations
  *          can not be changed via modification of elements of an array
--- a/test/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.java	Fri Jun 01 11:46:14 2012 -0700
@@ -25,7 +25,7 @@
 
 /*
   test %W% %E%
-  @bug 4874070
+  @bug 4874070 7146550
   @summary Tests basic DnD functionality
   @author Your Name: Alexey Utkin area=dnd
   @run applet ImageDecoratedDnDNegative.html
--- a/test/java/util/Collection/BiggernYours.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/util/Collection/BiggernYours.java	Fri Jun 01 11:46:14 2012 -0700
@@ -34,15 +34,25 @@
 
 @SuppressWarnings("unchecked")
 public class BiggernYours {
-    static final Random rnd = new Random();
+    static final Random rnd = new Random(18675309);
 
     static void compareCollections(Collection c1, Collection c2) {
-        arrayEqual(c1.toArray(),
-                   c2.toArray());
-        arrayEqual(c1.toArray(new Object[0]),
-                   c2.toArray(new Object[0]));
-        arrayEqual(c1.toArray(new Object[5]),
-                   c2.toArray(new Object[5]));
+        Object[] c1Array = c1.toArray();
+        Object[] c2Array = c2.toArray();
+
+        check(c1Array.length == c2Array.length);
+        for(Object aC1 : c1Array) {
+            boolean found = false;
+            for(Object aC2 : c2Array) {
+                if(Objects.equals(aC1, aC2)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if(!found)
+                fail(aC1 + " not found in " + Arrays.toString(c2Array));
+        }
     }
 
     static void compareMaps(Map m1, Map m2) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/HashMap/NullKeyAtResize.java	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7173432
+ * @summary If the key to be inserted into a HashMap is null and the table
+ * needs to be resized as part of the insertion then addEntry will try to
+ * recalculate the hash of a null key. This will fail with an NPE.
+ */
+
+import java.util.*;
+
+public class NullKeyAtResize {
+    public static void main(String[] args) throws Exception {
+        List<Object> old_order = new ArrayList<>();
+        Map<Object,Object> m = new HashMap<>(16);
+        int number = 0;
+        while(number < 100000) {
+            m.put(null,null); // try to put in null. This may cause resize.
+            m.remove(null); // remove it.
+            Integer adding = (number += 100);
+            m.put(adding, null); // try to put in a number. This wont cause resize.
+            List<Object> new_order = new ArrayList<>();
+            new_order.addAll(m.keySet());
+            new_order.remove(adding);
+            if(!old_order.equals(new_order)) {
+                // we resized and didn't crash.
+                System.out.println("Encountered resize after " + (number / 100) + " iterations");
+                break;
+            }
+            // remember this order for the next time around.
+            old_order.clear();
+            old_order.addAll(m.keySet());
+        }
+        if(number == 100000) {
+            throw new Error("Resize never occurred");
+        }
+    }
+}
--- a/test/java/util/Hashtable/HashCode.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/util/Hashtable/HashCode.java	Fri Jun 01 11:46:14 2012 -0700
@@ -36,8 +36,5 @@
         if (m.hashCode() != 0)
             throw new Exception("Empty Hashtable has nonzero hashCode.");
 
-        m.put("Joe", "Blow");
-        if (m.hashCode() != ("Joe".hashCode() ^ "Blow".hashCode()))
-            throw new Exception("Non-empty Hashtable has wrong hashCode.");
     }
 }
--- a/test/java/util/Hashtable/SimpleSerialization.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/util/Hashtable/SimpleSerialization.java	Fri Jun 01 11:46:14 2012 -0700
@@ -34,48 +34,58 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Hashtable;
+import java.util.Map;
 
 public class SimpleSerialization {
     public static void main(final String[] args) throws Exception {
         Hashtable<String, String> h1 = new Hashtable<>();
 
+        System.err.println("*** BEGIN TEST ***");
+
         h1.put("key", "value");
 
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        final ObjectOutputStream oos = new ObjectOutputStream(baos);
-
-        oos.writeObject(h1);
-        oos.close();
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(h1);
+        }
 
         final byte[] data = baos.toByteArray();
         final ByteArrayInputStream bais = new ByteArrayInputStream(data);
-        final ObjectInputStream ois = new ObjectInputStream(bais);
+        final Object deserializedObject;
+        try (ObjectInputStream ois = new ObjectInputStream(bais)) {
+            deserializedObject = ois.readObject();
+        }
 
-        final Object deserializedObject = ois.readObject();
-        ois.close();
+        if(!h1.getClass().isInstance(deserializedObject)) {
+             throw new RuntimeException("Result not assignable to type of h1");
+        }
 
         if (false == h1.equals(deserializedObject)) {
+             Hashtable<String, String> d1 = (Hashtable<String, String>) h1;
+            for(Map.Entry entry: h1.entrySet()) {
+                System.err.println("h1.key::" + entry.getKey() + " d1.containsKey()::" + d1.containsKey((String) entry.getKey()));
+                System.err.println("h1.value::" + entry.getValue() + " d1.contains()::" + d1.contains(entry.getValue()));
+                System.err.println("h1.value == d1.value " + entry.getValue().equals(d1.get((String) entry.getKey())));
+            }
+
             throw new RuntimeException(getFailureText(h1, deserializedObject));
         }
     }
 
     private static String getFailureText(final Object orig, final Object copy) {
         final StringWriter sw = new StringWriter();
-        final PrintWriter pw = new PrintWriter(sw);
-
-        pw.println("Test FAILED: Deserialized object is not equal to the original object");
-        pw.print("\tOriginal: ");
-        printObject(pw, orig).println();
-        pw.print("\tCopy:     ");
-        printObject(pw, copy).println();
-
-        pw.close();
+        try (PrintWriter pw = new PrintWriter(sw)) {
+            pw.println("Test FAILED: Deserialized object is not equal to the original object");
+            pw.print("\tOriginal: ");
+            printObject(pw, orig).println();
+            pw.print("\tCopy:     ");
+            printObject(pw, copy).println();
+        }
         return sw.toString();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Map/Collisions.java	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7126277
+ * @summary Ensure Maps behave well with lots of hashCode() collisions.
+ * @author Mike Duigou
+ */
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+public class Collisions {
+
+    final static class HashableInteger implements Comparable<HashableInteger> {
+
+        final int value;
+        final int hashmask; //yes duplication
+
+        HashableInteger(int value, int hashmask) {
+            this.value = value;
+            this.hashmask = hashmask;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof HashableInteger) {
+                HashableInteger other = (HashableInteger) obj;
+
+                return other.value == value;
+            }
+
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return value % hashmask;
+        }
+
+        @Override
+        public int compareTo(HashableInteger o) {
+            return value - o.value;
+        }
+
+        public String toString() {
+            return Integer.toString(value);
+        }
+    }
+    private static final int ITEMS = 10000;
+    private static final Object KEYS[][];
+
+    static {
+        HashableInteger UNIQUE_OBJECTS[] = new HashableInteger[ITEMS];
+        HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[ITEMS];
+        String UNIQUE_STRINGS[] = new String[ITEMS];
+        String COLLIDING_STRINGS[] = new String[ITEMS];
+
+        for (int i = 0; i < ITEMS; i++) {
+            UNIQUE_OBJECTS[i] = new HashableInteger(i, Integer.MAX_VALUE);
+            COLLIDING_OBJECTS[i] = new HashableInteger(i, 10);
+            UNIQUE_STRINGS[i] = unhash(i);
+            COLLIDING_STRINGS[i] = (0 == i % 2)
+                    ? UNIQUE_STRINGS[i / 2]
+                    : "\u0000\u0000\u0000\u0000\u0000" + COLLIDING_STRINGS[i - 1];
+        }
+
+     KEYS = new Object[][] {
+            new Object[]{"Unique Objects", UNIQUE_OBJECTS},
+            new Object[]{"Colliding Objects", COLLIDING_OBJECTS},
+            new Object[]{"Unique Strings", UNIQUE_STRINGS},
+            new Object[]{"Colliding Strings", COLLIDING_STRINGS}
+        };
+    }
+
+    /**
+     * Returns a string with a hash equal to the argument.
+     *
+     * @return string with a hash equal to the argument.
+     */
+    public static String unhash(int target) {
+        StringBuilder answer = new StringBuilder();
+        if (target < 0) {
+            // String with hash of Integer.MIN_VALUE, 0x80000000
+            answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
+
+            if (target == Integer.MIN_VALUE) {
+                return answer.toString();
+            }
+            // Find target without sign bit set
+            target = target & Integer.MAX_VALUE;
+        }
+
+        unhash0(answer, target);
+        return answer.toString();
+    }
+
+    private static void unhash0(StringBuilder partial, int target) {
+        int div = target / 31;
+        int rem = target % 31;
+
+        if (div <= Character.MAX_VALUE) {
+            if (div != 0) {
+                partial.append((char) div);
+            }
+            partial.append((char) rem);
+        } else {
+            unhash0(partial, div);
+            partial.append((char) rem);
+        }
+    }
+
+    private static void realMain(String[] args) throws Throwable {
+        for (Object[] keys_desc : KEYS) {
+            Map<Object, Boolean>[] MAPS = (Map<Object, Boolean>[]) new Map[]{
+                        new Hashtable<>(),
+                        new HashMap<>(),
+                        new IdentityHashMap<>(),
+                        new LinkedHashMap<>(),
+                        new ConcurrentHashMap<>(),
+                        new WeakHashMap<>(),
+                        new TreeMap<>(),
+                        new ConcurrentSkipListMap<>()
+                    };
+
+            for (Map<Object, Boolean> map : MAPS) {
+                String desc = (String) keys_desc[0];
+                Object[] keys = (Object[]) keys_desc[1];
+                testMap(map, desc, keys);
+            }
+        }
+    }
+
+    private static <T> void testMap(Map<T, Boolean> map, String keys_desc, T[] keys) {
+        System.err.println(map.getClass() + " : " + keys_desc);
+        testInsertion(map, keys_desc, keys);
+
+        if (keys[0] instanceof HashableInteger) {
+            testIntegerIteration((Map<HashableInteger, Boolean>) map, (HashableInteger[]) keys);
+        } else {
+            testStringIteration((Map<String, Boolean>) map, (String[]) keys);
+        }
+
+        testContainsKey(map, keys_desc, keys);
+
+        testRemove(map, keys_desc, keys);
+
+        check(map.isEmpty());
+    }
+
+    private static <T> void testInsertion(Map<T, Boolean> map, String keys_desc, T[] keys) {
+        check("map empty", (map.size() == 0) && map.isEmpty());
+
+        for (int i = 0; i < keys.length; i++) {
+            check(String.format("insertion: map expected size m%d != i%d", map.size(), i),
+                    map.size() == i);
+            check(String.format("insertion: put(%s[%d])", keys_desc, i), null == map.put(keys[i], true));
+            check(String.format("insertion: containsKey(%s[%d])", keys_desc, i), map.containsKey(keys[i]));
+        }
+
+        check(String.format("map expected size m%d != k%d", map.size(), keys.length),
+                map.size() == keys.length);
+    }
+
+    private static void testIntegerIteration(Map<HashableInteger, Boolean> map, HashableInteger[] keys) {
+        check(String.format("map expected size m%d != k%d", map.size(), keys.length),
+                map.size() == keys.length);
+
+        BitSet all = new BitSet(keys.length);
+        for (Map.Entry<HashableInteger, Boolean> each : map.entrySet()) {
+            check("Iteration: key already seen", !all.get(each.getKey().value));
+            all.set(each.getKey().value);
+        }
+
+        all.flip(0, keys.length);
+        check("Iteration: some keys not visited", all.isEmpty());
+
+        for (HashableInteger each : map.keySet()) {
+            check("Iteration: key already seen", !all.get(each.value));
+            all.set(each.value);
+        }
+
+        all.flip(0, keys.length);
+        check("Iteration: some keys not visited", all.isEmpty());
+
+        int count = 0;
+        for (Boolean each : map.values()) {
+            count++;
+        }
+
+        check(String.format("Iteration: value count matches size m%d != c%d", map.size(), count),
+                map.size() == count);
+    }
+
+    private static void testStringIteration(Map<String, Boolean> map, String[] keys) {
+        check(String.format("map expected size m%d != k%d", map.size(), keys.length),
+                map.size() == keys.length);
+
+        BitSet all = new BitSet(keys.length);
+        for (Map.Entry<String, Boolean> each : map.entrySet()) {
+            String key = each.getKey();
+            boolean longKey = key.length() > 5;
+            int index = key.hashCode() + (longKey ? keys.length / 2 : 0);
+            check("key already seen", !all.get(index));
+            all.set(index);
+        }
+
+        all.flip(0, keys.length);
+        check("some keys not visited", all.isEmpty());
+
+        for (String each : map.keySet()) {
+            boolean longKey = each.length() > 5;
+            int index = each.hashCode() + (longKey ? keys.length / 2 : 0);
+            check("key already seen", !all.get(index));
+            all.set(index);
+        }
+
+        all.flip(0, keys.length);
+        check("some keys not visited", all.isEmpty());
+
+        int count = 0;
+        for (Boolean each : map.values()) {
+            count++;
+        }
+
+        check(String.format("value count matches size m%d != k%d", map.size(), keys.length),
+                map.size() == keys.length);
+    }
+
+    private static <T> void testContainsKey(Map<T, Boolean> map, String keys_desc, T[] keys) {
+        for (int i = 0; i < keys.length; i++) {
+            T each = keys[i];
+            check("containsKey: " + keys_desc + "[" + i + "]" + each, map.containsKey(each));
+        }
+    }
+
+    private static <T> void testRemove(Map<T, Boolean> map, String keys_desc, T[] keys) {
+        check(String.format("remove: map expected size m%d != k%d", map.size(), keys.length),
+                map.size() == keys.length);
+
+        for (int i = 0; i < keys.length; i++) {
+            T each = keys[i];
+            check("remove: " + keys_desc + "[" + i + "]" + each, null != map.remove(each));
+        }
+
+        check(String.format("remove: map empty. size=%d", map.size()),
+                (map.size() == 0) && map.isEmpty());
+    }
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+
+    static void pass() {
+        passed++;
+    }
+
+    static void fail() {
+        failed++;
+        (new Error("Failure")).printStackTrace(System.err);
+    }
+
+    static void fail(String msg) {
+        failed++;
+        (new Error("Failure: " + msg)).printStackTrace(System.err);
+    }
+
+    static void abort() {
+        fail();
+        System.exit(1);
+    }
+
+    static void abort(String msg) {
+        fail(msg);
+        System.exit(1);
+    }
+
+    static void unexpected(String msg, Throwable t) {
+        System.err.println("Unexpected: " + msg);
+        unexpected(t);
+    }
+
+    static void unexpected(Throwable t) {
+        failed++;
+        t.printStackTrace(System.err);
+    }
+
+    static void check(boolean cond) {
+        if (cond) {
+            pass();
+        } else {
+            fail();
+        }
+    }
+
+    static void check(String desc, boolean cond) {
+        if (cond) {
+            pass();
+        } else {
+            fail(desc);
+        }
+    }
+
+    static void equal(Object x, Object y) {
+        if (Objects.equals(x, y)) {
+            pass();
+        } else {
+            fail(x + " not equal to " + y);
+        }
+    }
+
+    public static void main(String[] args) throws Throwable {
+        Thread.currentThread().setName("Collisions");
+//        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
+        try {
+            realMain(args);
+        } catch (Throwable t) {
+            unexpected(t);
+        }
+
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) {
+            throw new Error("Some tests failed");
+        }
+    }
+}
--- a/test/java/util/Map/Get.java	Thu May 31 14:06:48 2012 -0700
+++ b/test/java/util/Map/Get.java	Fri Jun 01 11:46:14 2012 -0700
@@ -50,16 +50,16 @@
                             Character key, Boolean value,
                             Boolean oldValue) {
         if (oldValue != null) {
-            check(m.containsValue(oldValue));
-            check(m.values().contains(oldValue));
+            check("containsValue(oldValue)", m.containsValue(oldValue));
+            check("values.contains(oldValue)", m.values().contains(oldValue));
         }
         equal(m.put(key, value), oldValue);
         equal(m.get(key), value);
-        check(m.containsKey(key));
-        check(m.keySet().contains(key));
-        check(m.containsValue(value));
-        check(m.values().contains(value));
-        check(! m.isEmpty());
+        check("containsKey", m.containsKey(key));
+        check("keySet.contains", m.keySet().contains(key));
+        check("containsValue", m.containsValue(value));
+        check("values.contains",  m.values().contains(value));
+        check("!isEmpty", ! m.isEmpty());
     }
 
     private static void testMap(Map<Character,Boolean> m) {
@@ -71,7 +71,7 @@
                                         m instanceof Hashtable));
         boolean usesIdentity = m instanceof IdentityHashMap;
 
-        System.out.println(m.getClass());
+        System.err.println(m.getClass());
         put(m, 'A', true,  null);
         put(m, 'A', false, true);       // Guaranteed identical by JLS
         put(m, 'B', true,  null);
@@ -81,15 +81,15 @@
                 put(m, null, true,  null);
                 put(m, null, false, true);
             }
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
         } else {
-            try { m.get(null); fail(); }
+            try { m.get(null); fail(m.getClass().getName() + " did not reject null key"); }
             catch (NullPointerException e) {}
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
 
-            try { m.put(null, true); fail(); }
+            try { m.put(null, true); fail(m.getClass().getName() + " did not reject null key"); }
             catch (NullPointerException e) {}
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
         }
         if (permitsNullValues) {
             try {
@@ -97,33 +97,35 @@
                 put(m, 'C', true, null);
                 put(m, 'C', null, true);
             }
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
         } else {
-            try { m.put('A', null); fail(); }
+            try { m.put('A', null); fail(m.getClass().getName() + " did not reject null key"); }
             catch (NullPointerException e) {}
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
 
-            try { m.put('C', null); fail(); }
+            try { m.put('C', null); fail(m.getClass().getName() + " did not reject null key"); }
             catch (NullPointerException e) {}
-            catch (Throwable t) { unexpected(t); }
+            catch (Throwable t) { unexpected(m.getClass().getName(), t); }
         }
     }
 
     //--------------------- Infrastructure ---------------------------
     static volatile int passed = 0, failed = 0;
     static void pass() { passed++; }
-    static void fail() { failed++; Thread.dumpStack(); }
-    static void fail(String msg) { System.out.println(msg); fail(); }
-    static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
+    static void fail() { failed++; (new Error("Failure")).printStackTrace(System.err); }
+    static void fail(String msg) { failed++; (new Error("Failure: " + msg)).printStackTrace(System.err); }
+    static void unexpected(String msg, Throwable t) { System.err.println("Unexpected: " + msg); unexpected(t); }
+    static void unexpected(Throwable t) { failed++; t.printStackTrace(System.err); }
     static void check(boolean cond) { if (cond) pass(); else fail(); }
+    static void check(String desc, boolean cond) { if (cond) pass(); else fail(desc); }
     static void equal(Object x, Object y) {
-        if (x == null ? y == null : x.equals(y)) pass();
-        else {System.out.println(x + " not equal to " + y); fail(); }}
+        if(Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
+    }
 
     public static void main(String[] args) throws Throwable {
         try { realMain(args); } catch (Throwable t) { unexpected(t); }
 
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
-        if (failed > 0) throw new Exception("Some tests failed");
+        if (failed > 0) throw new Error("Some tests failed");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/JSpinner/5012888/bug5012888.java	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test 1.0 04/04/23
+   @bug 5012888
+   @summary REGRESSION: Click & hold on arrow of JSpinner only transfers focus
+   @author Konstantin Eremin
+   @run main bug5012888
+*/
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+
+public class bug5012888 extends JFrame {
+    JSpinner spinner1, spinner2;
+    public bug5012888() {
+      spinner1 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000, 1));
+      spinner2 = new JSpinner(new SpinnerNumberModel(1, -1000, 1000, 1));
+      Container pane = getContentPane();
+      pane.setLayout(new BorderLayout());
+      pane.add(spinner1, BorderLayout.NORTH);
+      pane.add(spinner2, BorderLayout.SOUTH);
+    }
+    public void doTest() throws Exception {
+        ((sun.awt.SunToolkit)Toolkit.getDefaultToolkit()).realSync();
+        Point p = spinner2.getLocationOnScreen();
+        Rectangle rect = spinner2.getBounds();
+        Robot robot = new Robot();
+        robot.mouseMove(p.x+rect.width-5, p.y+5);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        Thread.sleep(1000);
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        if ( ((Integer) spinner2.getValue()).intValue() == 1 ) {
+            throw new Error("Spinner value should be more than 1");
+        }
+    }
+    public static void main(String[] argv) throws Exception {
+        bug5012888 b = new bug5012888();
+        b.setBounds(0, 0, 100, 100);
+        b.setVisible(true);
+        b.doTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/Hashing.java	Fri Jun 01 11:46:14 2012 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test @summary Ensure that Murmur3 hash performs according to specification.
+ * @compile -XDignore.symbol.file Hashing.java
+ */
+public class Hashing {
+
+    static final byte ONE_BYTE[] = {
+        (byte) 0x80};
+    static final byte TWO_BYTE[] = {
+        (byte) 0x80, (byte) 0x81};
+    static final char ONE_CHAR[] = {
+        (char) 0x8180};
+    static final byte THREE_BYTE[] = {
+        (byte) 0x80, (byte) 0x81, (byte) 0x82};
+    static final byte FOUR_BYTE[] = {
+        (byte) 0x80, (byte) 0x81, (byte) 0x82, (byte) 0x83};
+    static final char TWO_CHAR[] = {
+        (char) 0x8180, (char) 0x8382};
+    static final int ONE_INT[] = {
+        0x83828180};
+    static final byte SIX_BYTE[] = {
+        (byte) 0x80, (byte) 0x81, (byte) 0x82,
+        (byte) 0x83, (byte) 0x84, (byte) 0x85};
+    static final char THREE_CHAR[] = {
+        (char) 0x8180, (char) 0x8382, (char) 0x8584};
+    static final byte EIGHT_BYTE[] = {
+        (byte) 0x80, (byte) 0x81, (byte) 0x82,
+        (byte) 0x83, (byte) 0x84, (byte) 0x85,
+        (byte) 0x86, (byte) 0x87};
+    static final char FOUR_CHAR[] = {
+        (char) 0x8180, (char) 0x8382,
+        (char) 0x8584, (char) 0x8786};
+    static final int TWO_INT[] = {
+        0x83828180, 0x87868584};
+    // per  http://code.google.com/p/smhasher/source/browse/trunk/main.cpp, line:72
+    static final int MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;
+
+    public static void testMurmur3_32_ByteArray() {
+        System.out.println("testMurmur3_32_ByteArray");
+
+        byte[] vector = new byte[256];
+        byte[] hashes = new byte[4 * 256];
+
+        for (int i = 0; i < 256; i++) {
+            vector[i] = (byte) i;
+        }
+
+        // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
+        for (int i = 0; i < 256; i++) {
+            int hash = sun.misc.Hashing.murmur3_32(256 - i, vector, 0, i);
+
+            hashes[i * 4] = (byte) hash;
+            hashes[i * 4 + 1] = (byte) (hash >>> 8);
+            hashes[i * 4 + 2] = (byte) (hash >>> 16);
+            hashes[i * 4 + 3] = (byte) (hash >>> 24);
+        }
+
+        // hash to get final result.
+        int final_hash = sun.misc.Hashing.murmur3_32(0, hashes);
+
+        if (MURMUR3_32_X86_CHECK_VALUE != final_hash) {
+            throw new RuntimeException(
+                    String.format("Calculated hash result not as expected. Expected %08X got %08X",
+                    MURMUR3_32_X86_CHECK_VALUE,
+                    final_hash));
+        }
+    }
+
+    public static void testEquivalentHashes() {
+        int bytes, chars, ints;
+
+        System.out.println("testEquivalentHashes");
+
+        bytes = sun.misc.Hashing.murmur3_32(TWO_BYTE);
+        chars = sun.misc.Hashing.murmur3_32(ONE_CHAR);
+        if (bytes != chars) {
+            throw new RuntimeException(String.format("Hashes did not match. b:%08x != c:%08x", bytes, chars));
+        }
+
+        bytes = sun.misc.Hashing.murmur3_32(FOUR_BYTE);
+        chars = sun.misc.Hashing.murmur3_32(TWO_CHAR);
+        ints = sun.misc.Hashing.murmur3_32(ONE_INT);
+        if ((bytes != chars) || (bytes != ints)) {
+            throw new RuntimeException(String.format("Hashes did not match. b:%08x != c:%08x != i:%08x", bytes, chars, ints));
+        }
+        bytes = sun.misc.Hashing.murmur3_32(SIX_BYTE);
+        chars = sun.misc.Hashing.murmur3_32(THREE_CHAR);
+        if (bytes != chars) {
+            throw new RuntimeException(String.format("Hashes did not match. b:%08x != c:%08x", bytes, chars));
+        }
+
+        bytes = sun.misc.Hashing.murmur3_32(EIGHT_BYTE);
+        chars = sun.misc.Hashing.murmur3_32(FOUR_CHAR);
+        ints = sun.misc.Hashing.murmur3_32(TWO_INT);
+        if ((bytes != chars) || (bytes != ints)) {
+            throw new RuntimeException(String.format("Hashes did not match. b:%08x != c:%08x != i:%08x", bytes, chars, ints));
+        }
+    }
+
+    public static void main(String[] args) {
+        testMurmur3_32_ByteArray();
+        testEquivalentHashes();
+    }
+}