changeset 2593:6df81d93af9c

Add 2012/10/16 security updates. 2012-10-11 Andrew John Hughes <gnu.andrew@redhat.com> * Makefile.am: (SECURITY_PATCHES): Add new patches. * patches/ecj/override.patch: Add new cases in P11Key and RMIConnectionImpl introduced by security patches. * patches/ssl.patch: Removed old unneeded patch which breaks with this update. * patches/security/20111018/7092186.patch: Backport of patch added to OpenJDK6 by Oracle as part of the last security update but not included in the bundle delivered ahead of time. * patches/security/20121016/6631398.patch, * patches/security/20121016/7093490.patch, * patches/security/20121016/7143535.patch, * patches/security/20121016/7158801.patch, * patches/security/20121016/7167656.patch, * patches/security/20121016/7169884.patch, * patches/security/20121016/7169888.patch, * patches/security/20121016/7172522.patch, * patches/security/20121016/7176337.patch, * patches/security/20121016/7186286.patch, * patches/security/20121016/7189103.patch, * patches/security/20121016/7189490.patch, * patches/security/20121016/7189567.patch, * patches/security/20121016/7192975.patch, * patches/security/20121016/7195194.patch, * patches/security/20121016/7195917.patch, * patches/security/20121016/7195919.patch, * patches/security/20121016/7198296.patch, * patches/security/20121016/7198606.patch, * patches/security/20121016/hs20/7158800.patch, * patches/security/20121016/hs20/7158804.patch, * patches/security/20121016/original/7158800.patch, * patches/security/20121016/original/7158804.patch: New patches.
author Andrew John Hughes <ahughes@redhat.com>
date Fri, 12 Oct 2012 02:18:24 +0100
parents d64dd8e0811e
children bab6ae8c1c86
files ChangeLog Makefile.am patches/ecj/override.patch patches/security/20111018/7092186.patch patches/security/20121016/6631398.patch patches/security/20121016/7093490.patch patches/security/20121016/7143535.patch patches/security/20121016/7158801.patch patches/security/20121016/7167656.patch patches/security/20121016/7169884.patch patches/security/20121016/7169888.patch patches/security/20121016/7172522.patch patches/security/20121016/7176337.patch patches/security/20121016/7186286.patch patches/security/20121016/7189103.patch patches/security/20121016/7189490.patch patches/security/20121016/7189567.patch patches/security/20121016/7192975.patch patches/security/20121016/7195194.patch patches/security/20121016/7195917.patch patches/security/20121016/7195919.patch patches/security/20121016/7198296.patch patches/security/20121016/7198606.patch patches/security/20121016/hs20/7158800.patch patches/security/20121016/hs20/7158804.patch patches/security/20121016/original/7158800.patch patches/security/20121016/original/7158804.patch patches/ssl.patch
diffstat 28 files changed, 4786 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Sep 05 11:43:29 2012 +0200
+++ b/ChangeLog	Fri Oct 12 02:18:24 2012 +0100
@@ -1,3 +1,42 @@
+2012-10-11  Andrew John Hughes  <gnu.andrew@redhat.com>
+
+	* Makefile.am:
+	(SECURITY_PATCHES): Add new patches.
+	* patches/ecj/override.patch:
+	Add new cases in P11Key and RMIConnectionImpl
+	introduced by security patches.
+	* patches/ssl.patch:
+	Removed old unneeded patch which breaks with
+	this update.
+	* patches/security/20111018/7092186.patch:
+	Backport of patch added to OpenJDK6 by Oracle
+	as part of the last security update but not
+	included in the bundle delivered ahead of time.
+	* patches/security/20121016/6631398.patch,
+	* patches/security/20121016/7093490.patch,
+	* patches/security/20121016/7143535.patch,
+	* patches/security/20121016/7158801.patch,
+	* patches/security/20121016/7167656.patch,
+	* patches/security/20121016/7169884.patch,
+	* patches/security/20121016/7169888.patch,
+	* patches/security/20121016/7172522.patch,
+	* patches/security/20121016/7176337.patch,
+	* patches/security/20121016/7186286.patch,
+	* patches/security/20121016/7189103.patch,
+	* patches/security/20121016/7189490.patch,
+	* patches/security/20121016/7189567.patch,
+	* patches/security/20121016/7192975.patch,
+	* patches/security/20121016/7195194.patch,
+	* patches/security/20121016/7195917.patch,
+	* patches/security/20121016/7195919.patch,
+	* patches/security/20121016/7198296.patch,
+	* patches/security/20121016/7198606.patch,
+	* patches/security/20121016/hs20/7158800.patch,
+	* patches/security/20121016/hs20/7158804.patch,
+	* patches/security/20121016/original/7158800.patch,
+	* patches/security/20121016/original/7158804.patch:
+	New patches.
+
 2012-09-05  Matthias Klose  <doko@ubuntu.com>
 
 	* configure.ac: Remove the Xp header and library checks.
--- a/Makefile.am	Wed Sep 05 11:43:29 2012 +0200
+++ b/Makefile.am	Fri Oct 12 02:18:24 2012 +0100
@@ -207,6 +207,7 @@
 	patches/security/20111018/7096936.patch \
 	patches/security/20111018/7046794.patch \
 	patches/security/20111018/7077466.patch \
+	patches/security/20111018/7092186.patch \
 	patches/security/20120214/7082299.patch \
 	patches/security/20120214/7088367.patch \
 	patches/security/20120214/7110683.patch \
@@ -229,7 +230,28 @@
 	patches/security/20120612/7160757.patch \
 	patches/security/20120830/7162476-xmldecoder_via_classfinder.patch \
 	patches/security/20120830/7163201-simplify_toolkit_internal_references.patch \
-	patches/security/20120830/7182135-impossible_to_use_some_editors_directly.patch
+	patches/security/20120830/7182135-impossible_to_use_some_editors_directly.patch \
+	patches/security/20121016/6631398.patch \
+	patches/security/20121016/7093490.patch \
+	patches/security/20121016/7143535.patch \
+	patches/security/20121016/${HSBUILD}/7158800.patch \
+	patches/security/20121016/7158801.patch \
+	patches/security/20121016/${HSBUILD}/7158804.patch \
+	patches/security/20121016/7167656.patch \
+	patches/security/20121016/7169884.patch \
+	patches/security/20121016/7169888.patch \
+	patches/security/20121016/7172522.patch \
+	patches/security/20121016/7176337.patch \
+	patches/security/20121016/7186286.patch \
+	patches/security/20121016/7189103.patch \
+	patches/security/20121016/7189490.patch \
+	patches/security/20121016/7189567.patch \
+	patches/security/20121016/7192975.patch \
+	patches/security/20121016/7195194.patch \
+	patches/security/20121016/7195917.patch \
+	patches/security/20121016/7195919.patch \
+	patches/security/20121016/7198296.patch \
+	patches/security/20121016/7198606.patch
 
 SPECIAL_SECURITY_PATCH = patches/security/20120214/7112642.patch
 
@@ -266,7 +288,6 @@
 	patches/version.patch \
 	patches/hotspot/$(HSBUILD)/version-hotspot.patch \
 	patches/hotspot/$(HSBUILD)/text-relocations.patch \
-	patches/ssl.patch \
 	patches/rmi_amd64.patch \
 	patches/tools.patch \
 	patches/use-system-tzdata.patch \
--- a/patches/ecj/override.patch	Wed Sep 05 11:43:29 2012 +0200
+++ b/patches/ecj/override.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -229,3 +229,25 @@
          public int compareTo(X509IssuerSerial another) {
              int cissuer = issuer.toString()
                      .compareTo(another.issuer.toString());
+diff -Nru openjdk-ecj.orig/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java openjdk-ecj/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+--- openjdk-ecj.orig/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java	2012-10-11 19:58:37.130814619 +0100
++++ openjdk-ecj/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java	2012-10-11 19:59:39.699829277 +0100
+@@ -168,7 +168,6 @@
+         this.defaultContextClassLoader =
+             AccessController.doPrivileged(
+                 new PrivilegedAction<ClassLoader>() {
+-                    @Override
+                     public ClassLoader run() {
+                         return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
+                                 dcl);
+diff -Nru openjdk-ecj.orig/jdk/src/share/classes/sun/security/pkcs11/P11Key.java openjdk-ecj/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+--- openjdk-ecj.orig/jdk/src/share/classes/sun/security/pkcs11/P11Key.java	2012-10-11 20:18:07.340676704 +0100
++++ openjdk-ecj/jdk/src/share/classes/sun/security/pkcs11/P11Key.java	2012-10-11 20:17:40.092039288 +0100
+@@ -216,7 +216,6 @@
+     /**
+      * Return bit length of the key.
+      */
+-    @Override
+     public int length() { 
+         return keyLength;
+     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20111018/7092186.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,32 @@
+# HG changeset patch
+# User coffeys
+# Date 1317891250 -3600
+# Node ID cdc68d7a17dd412402b100dc427abbe0a90cf2ab
+# Parent  0c65618b5ae189882a5b0716a83d958d78a93edc
+7092186: adjust package access in rmiregistry
+Reviewed-by: smarks
+
+diff --git a/src/share/classes/sun/rmi/registry/RegistryImpl.java b/src/share/classes/sun/rmi/registry/RegistryImpl.java
+--- openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
++++ openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
+@@ -417,6 +417,8 @@
+          */
+         perms.add(new SocketPermission("*", "connect,accept"));
+ 
++        perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
++
+         // add permissions required to load from codebase URL path
+         LoaderHandler.addPermissionsForURLs(urls, perms, false);
+ 
+diff --git a/test/sun/tools/jstatd/jstatdExternalRegistry.sh b/test/sun/tools/jstatd/jstatdExternalRegistry.sh
+--- openjdk/jdk/test/sun/tools/jstatd/jstatdExternalRegistry.sh
++++ openjdk/jdk/test/sun/tools/jstatd/jstatdExternalRegistry.sh
+@@ -22,7 +22,7 @@
+ #
+ 
+ # @test
+-# @bug 4990825
++# @bug 4990825 7092186
+ # @run shell/timeout=90 jstatdExternalRegistry.sh
+ # @summary Test functionality of 'jstatd -p<port>&' with an external RMI registry
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/6631398.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,20 @@
+# HG changeset patch
+# User weijun
+# Date 1339724916 -28800
+# Node ID 0fdc422fba9b63be684f1229af75f0c1f3ceec87
+# Parent  f09937f0b2e32aa60a2cdd23f03a7e2d45091b60
+6631398: FilePermission improved path checking
+Reviewed-by: mullan, skoivu, jdn
+
+diff --git a/src/share/classes/java/io/FilePermission.java b/src/share/classes/java/io/FilePermission.java
+--- openjdk/jdk/src/share/classes/java/io/FilePermission.java
++++ openjdk/jdk/src/share/classes/java/io/FilePermission.java
+@@ -399,7 +399,7 @@
+      */
+ 
+     public int hashCode() {
+-        return this.cpath.hashCode();
++        return 0;
+     }
+ 
+     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7093490.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,28 @@
+# HG changeset patch
+# User coffeys
+# Date 1340913225 -3600
+# Node ID e7334bb16ad694bed492da52e5713c8391e79ce8
+# Parent  0fdc422fba9b63be684f1229af75f0c1f3ceec87
+7093490: adjust package access in rmiregistry
+Reviewed-by: smarks
+
+diff --git a/src/share/classes/sun/rmi/registry/RegistryImpl.java b/src/share/classes/sun/rmi/registry/RegistryImpl.java
+--- openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
++++ openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 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
+@@ -405,7 +405,8 @@
+          */
+         perms.add(new SocketPermission("*", "connect,accept"));
+ 
+-        perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
++        perms.add(new RuntimePermission("accessClassInPackage.sun.jvmstat.*"));
++        perms.add(new RuntimePermission("accessClassInPackage.sun.jvm.hotspot.*"));
+ 
+         perms.add(new FilePermission("<<ALL FILES>>", "read"));
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7143535.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,31 @@
+# HG changeset patch
+# User sundar
+# Date 1345469787 -14400
+# Node ID 1e170e3c1b682d0f98a61a47e5049535c5bd4999
+# Parent  e7334bb16ad694bed492da52e5713c8391e79ce8
+7143535: ScriptEngine corrected permissions
+Reviewed-by: mschoene
+
+diff --git a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
+--- openjdk/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
++++ openjdk/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2005, 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
+@@ -130,7 +130,11 @@
+     public RhinoScriptEngine() {
+ 
+         if (System.getSecurityManager() != null) {
+-            accCtxt = AccessController.getContext();
++            try {
++                AccessController.checkPermission(new AllPermission());
++            } catch (AccessControlException ace) {
++                accCtxt = AccessController.getContext();
++            }
+         }
+ 
+         Context cx = enterContext();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7158801.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,30 @@
+# HG changeset patch
+# User kvn
+# Date 1337800285 25200
+# Node ID f7493d50b47d3946902e18153bcd912e37589d00
+# Parent  2faa3f7bad65189e69ab2f9a491743786bb8f07f
+7158801: Improve VM CompileOnly option
+Summary: Fixed buffer overflow during parsing flags -XX:CompileCommand=, -XX:CompileOnly= and command lines in .hotspot_compiler file.
+Reviewed-by: never
+
+diff --git a/src/share/vm/compiler/compilerOracle.cpp b/src/share/vm/compiler/compilerOracle.cpp
+--- openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp
++++ openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp
+@@ -573,7 +573,7 @@
+   char token[1024];
+   int  pos = 0;
+   int  c = getc(stream);
+-  while(c != EOF) {
++  while(c != EOF && pos < (sizeof(token)-1)) {
+     if (c == '\n') {
+       token[pos++] = '\0';
+       parse_from_line(token);
+@@ -594,7 +594,7 @@
+   int  pos = 0;
+   const char* sp = str;
+   int  c = *sp++;
+-  while (c != '\0') {
++  while (c != '\0' && pos < (sizeof(token)-1)) {
+     if (c == '\n') {
+       token[pos++] = '\0';
+       parse_line(token);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7167656.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,75 @@
+# HG changeset patch
+# User coffeys
+# Date 1340139680 -3600
+# Node ID d04575148db287475168da344159e583f7bff02c
+# Parent  1e170e3c1b682d0f98a61a47e5049535c5bd4999
+7167656: Multiple Seeders are being created
+Reviewed-by: wetmore
+
+diff --git a/src/share/classes/sun/security/provider/SecureRandom.java b/src/share/classes/sun/security/provider/SecureRandom.java
+--- openjdk/jdk/src/share/classes/sun/security/provider/SecureRandom.java
++++ openjdk/jdk/src/share/classes/sun/security/provider/SecureRandom.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1998, 2003, 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,12 +56,6 @@
+ 
+     private static final long serialVersionUID = 3581829991155417889L;
+ 
+-    /**
+-     * This static object will be seeded by SeedGenerator, and used
+-     * to seed future instances of SecureRandom
+-     */
+-    private static SecureRandom seeder;
+-
+     private static final int DIGEST_SIZE = 20;
+     private transient MessageDigest digest;
+     private byte[] state;
+@@ -173,6 +167,28 @@
+     }
+ 
+     /**
++     * This static object will be seeded by SeedGenerator, and used
++     * to seed future instances of SHA1PRNG SecureRandoms.
++     *
++     * Bloch, Effective Java Second Edition: Item 71
++     */
++    private static class SeederHolder {
++
++        private static final SecureRandom seeder;
++
++        static {
++            /*
++             * Call to SeedGenerator.generateSeed() to add additional
++             * seed material (likely from the Native implementation).
++             */
++            seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
++            byte [] b = new byte[DIGEST_SIZE];
++            SeedGenerator.generateSeed(b);
++            seeder.engineSetSeed(b);
++        }
++    }
++
++    /**
+      * Generates a user-specified number of random bytes.
+      *
+      * @param bytes the array to be filled in with random bytes.
+@@ -183,13 +199,8 @@
+         byte[] output = remainder;
+ 
+         if (state == null) {
+-            if (seeder == null) {
+-                seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
+-                seeder.engineSetSeed(engineGenerateSeed(DIGEST_SIZE));
+-            }
+-
+             byte[] seed = new byte[DIGEST_SIZE];
+-            seeder.engineNextBytes(seed);
++            SeederHolder.seeder.engineNextBytes(seed);
+             state = digest.digest(seed);
+         }
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7169884.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,349 @@
+# HG changeset patch
+# User robm
+# Date 1347903606 -3600
+# Node ID 47e7c8e33cd82dade3e84af94bff125cdbdae062
+# Parent  d04575148db287475168da344159e583f7bff02c
+7169884: LogManager checks do not work correctly for sub-types
+Reviewed-by: alanb
+
+diff --git a/src/share/classes/java/util/logging/FileHandler.java b/src/share/classes/java/util/logging/FileHandler.java
+--- openjdk/jdk/src/share/classes/java/util/logging/FileHandler.java
++++ openjdk/jdk/src/share/classes/java/util/logging/FileHandler.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -220,7 +220,7 @@
+      * @exception  NullPointerException if pattern property is an empty String.
+      */
+     public FileHandler() throws IOException, SecurityException {
+-        checkAccess();
++        checkPermission();
+         configure();
+         openFiles();
+     }
+@@ -246,7 +246,7 @@
+         if (pattern.length() < 1 ) {
+             throw new IllegalArgumentException();
+         }
+-        checkAccess();
++        checkPermission();
+         configure();
+         this.pattern = pattern;
+         this.limit = 0;
+@@ -278,7 +278,7 @@
+         if (pattern.length() < 1 ) {
+             throw new IllegalArgumentException();
+         }
+-        checkAccess();
++        checkPermission();
+         configure();
+         this.pattern = pattern;
+         this.limit = 0;
+@@ -315,7 +315,7 @@
+         if (limit < 0 || count < 1 || pattern.length() < 1) {
+             throw new IllegalArgumentException();
+         }
+-        checkAccess();
++        checkPermission();
+         configure();
+         this.pattern = pattern;
+         this.limit = limit;
+@@ -354,7 +354,7 @@
+         if (limit < 0 || count < 1 || pattern.length() < 1) {
+             throw new IllegalArgumentException();
+         }
+-        checkAccess();
++        checkPermission();
+         configure();
+         this.pattern = pattern;
+         this.limit = limit;
+@@ -367,7 +367,7 @@
+     // configured instance variables.
+     private void openFiles() throws IOException {
+         LogManager manager = LogManager.getLogManager();
+-        manager.checkAccess();
++        manager.checkPermission();
+         if (count < 1) {
+            throw new IllegalArgumentException("file count = " + count);
+         }
+diff --git a/src/share/classes/java/util/logging/Handler.java b/src/share/classes/java/util/logging/Handler.java
+--- openjdk/jdk/src/share/classes/java/util/logging/Handler.java
++++ openjdk/jdk/src/share/classes/java/util/logging/Handler.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -111,7 +111,7 @@
+      *             the caller does not have <tt>LoggingPermission("control")</tt>.
+      */
+     public void setFormatter(Formatter newFormatter) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         // Check for a null pointer:
+         newFormatter.getClass();
+         formatter = newFormatter;
+@@ -140,7 +140,7 @@
+      */
+     public void setEncoding(String encoding)
+                         throws SecurityException, java.io.UnsupportedEncodingException {
+-        checkAccess();
++        checkPermission();
+         if (encoding != null) {
+             try {
+                 if(!java.nio.charset.Charset.isSupported(encoding)) {
+@@ -175,7 +175,7 @@
+      *             the caller does not have <tt>LoggingPermission("control")</tt>.
+      */
+     public void setFilter(Filter newFilter) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         filter = newFilter;
+     }
+ 
+@@ -199,7 +199,7 @@
+      *             the caller does not have <tt>LoggingPermission("control")</tt>.
+      */
+     public void setErrorManager(ErrorManager em) {
+-        checkAccess();
++        checkPermission();
+         if (em == null) {
+            throw new NullPointerException();
+         }
+@@ -213,7 +213,7 @@
+      *             the caller does not have <tt>LoggingPermission("control")</tt>.
+      */
+     public ErrorManager getErrorManager() {
+-        checkAccess();
++        checkPermission();
+         return errorManager;
+     }
+ 
+@@ -253,7 +253,7 @@
+         if (newLevel == null) {
+             throw new NullPointerException();
+         }
+-        checkAccess();
++        checkPermission();
+         logLevel = newLevel;
+     }
+ 
+@@ -296,9 +296,9 @@
+     // If "sealed" is true, we check that the caller has
+     // appropriate security privileges to update Handler
+     // state and if not throw a SecurityException.
+-    void checkAccess() throws SecurityException {
++    void checkPermission() throws SecurityException {
+         if (sealed) {
+-            manager.checkAccess();
++            manager.checkPermission();
+         }
+     }
+ }
+diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java
+--- openjdk/jdk/src/share/classes/java/util/logging/LogManager.java
++++ openjdk/jdk/src/share/classes/java/util/logging/LogManager.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -303,7 +303,7 @@
+         if (l == null) {
+             throw new NullPointerException();
+         }
+-        checkAccess();
++        checkPermission();
+         changes.addPropertyChangeListener(l);
+     }
+ 
+@@ -322,7 +322,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public void removePropertyChangeListener(PropertyChangeListener l) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         changes.removePropertyChangeListener(l);
+     }
+ 
+@@ -740,7 +740,7 @@
+      * @exception  IOException if there are IO problems reading the configuration.
+      */
+     public void readConfiguration() throws IOException, SecurityException {
+-        checkAccess();
++        checkPermission();
+ 
+         // if a configuration class is specified, load it and use it.
+         String cname = System.getProperty("java.util.logging.config.class");
+@@ -798,7 +798,7 @@
+      */
+ 
+     public void reset() throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         synchronized (this) {
+             props = new Properties();
+             // Since we are doing a reset we no longer want to initialize
+@@ -883,7 +883,7 @@
+      * @exception  IOException if there are problems reading from the stream.
+      */
+     public void readConfiguration(InputStream ins) throws IOException, SecurityException {
+-        checkAccess();
++        checkPermission();
+         reset();
+ 
+         // Load the properties
+@@ -1045,7 +1045,13 @@
+     }
+ 
+ 
+-    private Permission ourPermission = new LoggingPermission("control", null);
++    private final Permission controlPermission = new LoggingPermission("control", null);
++  
++    void checkPermission() {
++        SecurityManager sm = System.getSecurityManager();
++        if (sm != null)
++            sm.checkPermission(controlPermission);
++    }
+ 
+     /**
+      * Check that the current context is trusted to modify the logging
+@@ -1058,11 +1064,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public void checkAccess() throws SecurityException {
+-        SecurityManager sm = System.getSecurityManager();
+-        if (sm == null) {
+-            return;
+-        }
+-        sm.checkPermission(ourPermission);
++        checkPermission();
+     }
+ 
+     // Nested class to represent a node in our tree of named loggers.
+diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java
+--- openjdk/jdk/src/share/classes/java/util/logging/Logger.java
++++ openjdk/jdk/src/share/classes/java/util/logging/Logger.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -266,13 +266,13 @@
+         this.manager = manager;
+     }
+ 
+-    private void checkAccess() throws SecurityException {
++    private void checkPermission() throws SecurityException {
+         if (!anonymous) {
+             if (manager == null) {
+                 // Complete initialization of the global Logger.
+                 manager = LogManager.getLogManager();
+             }
+-            manager.checkAccess();
++            manager.checkPermission();
+         }
+     }
+ 
+@@ -454,7 +454,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public synchronized void setFilter(Filter newFilter) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         filter = newFilter;
+     }
+ 
+@@ -1145,7 +1145,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public void setLevel(Level newLevel) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         synchronized (treeLock) {
+             levelObject = newLevel;
+             updateEffectiveLevel();
+@@ -1200,7 +1200,7 @@
+     public synchronized void addHandler(Handler handler) throws SecurityException {
+         // Check for null handler
+         handler.getClass();
+-        checkAccess();
++        checkPermission();
+         if (handlers == null) {
+             handlers = new ArrayList<Handler>();
+         }
+@@ -1217,7 +1217,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public synchronized void removeHandler(Handler handler) throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         if (handler == null) {
+             return;
+         }
+@@ -1251,7 +1251,7 @@
+      *             the caller does not have LoggingPermission("control").
+      */
+     public synchronized void setUseParentHandlers(boolean useParentHandlers) {
+-        checkAccess();
++        checkPermission();
+         this.useParentHandlers = useParentHandlers;
+     }
+ 
+@@ -1388,7 +1388,7 @@
+         if (parent == null) {
+             throw new NullPointerException();
+         }
+-        manager.checkAccess();
++        manager.checkPermission();
+         doSetParent(parent);
+     }
+ 
+diff --git a/src/share/classes/java/util/logging/MemoryHandler.java b/src/share/classes/java/util/logging/MemoryHandler.java
+--- openjdk/jdk/src/share/classes/java/util/logging/MemoryHandler.java
++++ openjdk/jdk/src/share/classes/java/util/logging/MemoryHandler.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -238,7 +238,7 @@
+             throw new NullPointerException();
+         }
+         LogManager manager = LogManager.getLogManager();
+-        checkAccess();
++        checkPermission();
+         pushLevel = newLevel;
+     }
+ 
+diff --git a/src/share/classes/java/util/logging/StreamHandler.java b/src/share/classes/java/util/logging/StreamHandler.java
+--- openjdk/jdk/src/share/classes/java/util/logging/StreamHandler.java
++++ openjdk/jdk/src/share/classes/java/util/logging/StreamHandler.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -249,7 +249,7 @@
+     }
+ 
+     private synchronized void flushAndClose() throws SecurityException {
+-        checkAccess();
++        checkPermission();
+         if (writer != null) {
+             try {
+                 if (!doneHeader) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7169888.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,125 @@
+# HG changeset patch
+# User dbuck
+# Date 1342799616 25200
+# Node ID 39b599e90c7b33435ca42ae96ed673812a8be3d7
+# Parent  47e7c8e33cd82dade3e84af94bff125cdbdae062
+7169888: Narrowing resource definitions in JMX RMI connector
+Summary: see bugdb 13932219 for details
+Reviewed-by: fparain, vikram
+
+diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+--- openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
++++ openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002, 2007, 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
+@@ -39,11 +39,17 @@
+ import java.rmi.MarshalledObject;
+ import java.rmi.UnmarshalException;
+ import java.rmi.server.Unreferenced;
++
+ import java.security.AccessControlContext;
+ import java.security.AccessController;
++import java.security.Permission;
++import java.security.PermissionCollection;
++import java.security.Permissions;
+ import java.security.PrivilegedAction;
+ import java.security.PrivilegedActionException;
+ import java.security.PrivilegedExceptionAction;
++import java.security.ProtectionDomain;
++
+ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.Map;
+@@ -60,6 +66,7 @@
+ import javax.management.MBeanException;
+ import javax.management.MBeanInfo;
+ import javax.management.MBeanRegistrationException;
++import javax.management.MBeanPermission;
+ import javax.management.MBeanServer;
+ import javax.management.NotCompliantMBeanException;
+ import javax.management.NotificationFilter;
+@@ -144,15 +151,20 @@
+         this.mbeanServer = rmiServer.getMBeanServer();
+ 
+         final ClassLoader dcl = defaultClassLoader;
++
+         this.classLoaderWithRepository =
+             AccessController.doPrivileged(
+                 new PrivilegedAction<ClassLoaderWithRepository>() {
+                     public ClassLoaderWithRepository run() {
+                         return new ClassLoaderWithRepository(
+-                                              getClassLoaderRepository(),
++                                              mbeanServer.getClassLoaderRepository(),
+                                               dcl);
+                     }
+-                });
++                 },
++
++                 withPermissions( new MBeanPermission("*", "getClassLoaderRepository"),
++                                 new RuntimePermission("createClassLoader"))
++            );
+ 
+         serverCommunicatorAdmin = new
+           RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
+@@ -160,6 +172,17 @@
+         this.env = env;
+     }
+ 
++    private static AccessControlContext withPermissions(Permission ... perms){
++        Permissions col = new Permissions();
++
++        for (Permission thePerm : perms ) {
++            col.add(thePerm);
++        }
++
++        final ProtectionDomain pd = new ProtectionDomain(null, col);
++        return new AccessControlContext( new ProtectionDomain[] { pd });
++    }
++
+     private synchronized ServerNotifForwarder getServerNotifFwd() {
+         // Lazily created when first use. Mainly when
+         // addNotificationListener is first called.
+@@ -1314,16 +1337,6 @@
+     // private methods
+     //------------------------------------------------------------------------
+ 
+-    private ClassLoaderRepository getClassLoaderRepository() {
+-        return
+-            AccessController.doPrivileged(
+-                new PrivilegedAction<ClassLoaderRepository>() {
+-                    public ClassLoaderRepository run() {
+-                        return mbeanServer.getClassLoaderRepository();
+-                    }
+-                });
+-    }
+-
+     private ClassLoader getClassLoader(final ObjectName name)
+         throws InstanceNotFoundException {
+         try {
+@@ -1333,7 +1346,9 @@
+                         public ClassLoader run() throws InstanceNotFoundException {
+                             return mbeanServer.getClassLoader(name);
+                         }
+-                    });
++                    },
++                    withPermissions(new MBeanPermission("*", "getClassLoader"))
++            );
+         } catch (PrivilegedActionException pe) {
+             throw (InstanceNotFoundException) extractException(pe);
+         }
+@@ -1348,7 +1363,9 @@
+                         public Object run() throws InstanceNotFoundException {
+                             return mbeanServer.getClassLoaderFor(name);
+                         }
+-                    });
++                    },
++                    withPermissions(new MBeanPermission("*", "getClassLoaderFor"))
++            );
+         } catch (PrivilegedActionException pe) {
+             throw (InstanceNotFoundException) extractException(pe);
+         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7172522.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,36 @@
+# HG changeset patch
+# User coffeys
+# Date 1340096399 -3600
+# Node ID 88243aa6e67b6b84ff529ccdfd3b476410f60057
+# Parent  39b599e90c7b33435ca42ae96ed673812a8be3d7
+7172522: Improve DomainCombiner checking
+Reviewed-by: mullan
+
+diff --git a/src/share/classes/java/security/AccessController.java b/src/share/classes/java/security/AccessController.java
+--- openjdk/jdk/src/share/classes/java/security/AccessController.java
++++ openjdk/jdk/src/share/classes/java/security/AccessController.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 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
+@@ -293,7 +293,7 @@
+         DomainCombiner dc = null;
+         AccessControlContext acc = getStackAccessControlContext();
+         if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
+-            return AccessController.doPrivileged(action);
++            return AccessController.doPrivileged(action, acc);
+         }
+         return AccessController.doPrivileged(action, preserveCombiner(dc));
+     }
+@@ -389,7 +389,7 @@
+         DomainCombiner dc = null;
+         AccessControlContext acc = getStackAccessControlContext();
+         if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
+-            return AccessController.doPrivileged(action);
++            return AccessController.doPrivileged(action, acc);
+         }
+         return AccessController.doPrivileged(action, preserveCombiner(dc));
+     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7176337.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,29 @@
+# HG changeset patch
+# User asaha
+# Date 1340145914 25200
+# Node ID a148157cd348fe4c251063db7d3973a83cfcf483
+# Parent  fde4cc8479824449b03abedd5357500aec92e990
+7176337: Additional changes needed for 7158801 fix
+Reviewed-by: kvn
+
+diff --git a/src/share/vm/compiler/compilerOracle.cpp b/src/share/vm/compiler/compilerOracle.cpp
+--- openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp
++++ openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp
+@@ -573,7 +573,7 @@
+   char token[1024];
+   int  pos = 0;
+   int  c = getc(stream);
+-  while(c != EOF && pos < (sizeof(token)-1)) {
++  while(c != EOF && pos < (int)(sizeof(token)-1)) {
+     if (c == '\n') {
+       token[pos++] = '\0';
+       parse_from_line(token);
+@@ -594,7 +594,7 @@
+   int  pos = 0;
+   const char* sp = str;
+   int  c = *sp++;
+-  while (c != '\0' && pos < (sizeof(token)-1)) {
++  while (c != '\0' && pos < (int)(sizeof(token)-1)) {
+     if (c == '\n') {
+       token[pos++] = '\0';
+       parse_line(token);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7186286.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,552 @@
+# HG changeset patch
+# User xuelei
+# Date 1343546404 25200
+# Node ID a6294da5a21f609b67a0d4d216028dda9f56e689
+# Parent  88243aa6e67b6b84ff529ccdfd3b476410f60057
+7186286: TLS implementation to better adhere to RFC
+Summary: also reviewed by Alexander Fomin <Alexander.Fomin@Oracle.COM>, Andrew Gross<Andrew.Gross@Oracle.COM>, Sean Coffey<Sean.Coffey@Oracle.COM>
+Reviewed-by: valeriep, wetmore
+
+diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java
+--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
++++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 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
+@@ -650,7 +650,7 @@
+     // see JCE spec
+     protected int engineGetKeySize(Key key) throws InvalidKeyException {
+         int n = P11SecretKeyFactory.convertKey
+-                                (token, key, keyAlgorithm).keyLength();
++                                (token, key, keyAlgorithm).length();
+         return n;
+     }
+ }
+diff --git a/src/share/classes/sun/security/pkcs11/P11Key.java b/src/share/classes/sun/security/pkcs11/P11Key.java
+--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
++++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 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
+@@ -46,6 +46,7 @@
+ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+ 
+ import sun.security.util.DerValue;
++import sun.security.util.Length;
+ 
+ /**
+  * Key implementation classes.
+@@ -61,7 +62,7 @@
+  * @author  Andreas Sterbenz
+  * @since   1.5
+  */
+-abstract class P11Key implements Key {
++abstract class P11Key implements Key, Length {
+ 
+     private final static String PUBLIC = "public";
+     private final static String PRIVATE = "private";
+@@ -212,7 +213,11 @@
+         return s1;
+     }
+ 
+-    int keyLength() {
++    /**
++     * Return bit length of the key.
++     */
++    @Override
++    public int length() { 
+         return keyLength;
+     }
+ 
+diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
++++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 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
+@@ -201,7 +201,7 @@
+         } else {
+             throw new InvalidKeyException("Unknown key type: " + p11Key);
+         }
+-        int n = (p11Key.keyLength() + 7) >> 3;
++        int n = (p11Key.length() + 7) >> 3;
+         outputSize = n;
+         buffer = new byte[n];
+         maxInputSize = encrypt ? (n - PKCS1_MIN_PADDING_LENGTH) : n;
+@@ -458,7 +458,7 @@
+ 
+     // see JCE spec
+     protected int engineGetKeySize(Key key) throws InvalidKeyException {
+-        int n = P11KeyFactory.convertKey(token, key, algorithm).keyLength();
++        int n = P11KeyFactory.convertKey(token, key, algorithm).length();
+         return n;
+     }
+ }
+diff --git a/src/share/classes/sun/security/pkcs11/P11Signature.java b/src/share/classes/sun/security/pkcs11/P11Signature.java
+--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
++++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 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
+@@ -274,7 +274,7 @@
+                 if (keyAlgorithm.equals("DSA")) {
+                     signature = new byte[40];
+                 } else {
+-                    signature = new byte[(p11Key.keyLength() + 7) >> 3];
++                    signature = new byte[(p11Key.length() + 7) >> 3];
+                 }
+                 if (type == T_UPDATE) {
+                     token.p11.C_VerifyFinal(session.id(), signature);
+@@ -359,7 +359,7 @@
+         if (keyAlgorithm.equals("RSA") && publicKey != p11Key) {
+             int keyLen;
+             if (publicKey instanceof P11Key) {
+-                keyLen = ((P11Key) publicKey).keyLength();
++                keyLen = ((P11Key) publicKey).length();
+             } else {
+                 keyLen = ((RSAKey) publicKey).getModulus().bitLength();
+             }
+@@ -620,7 +620,7 @@
+ 
+     private byte[] pkcs1Pad(byte[] data) {
+         try {
+-            int len = (p11Key.keyLength() + 7) >> 3;
++            int len = (p11Key.length() + 7) >> 3;
+             RSAPadding padding = RSAPadding.getInstance
+                                         (RSAPadding.PAD_BLOCKTYPE_1, len);
+             byte[] padded = padding.pad(data);
+diff --git a/src/share/classes/sun/security/ssl/HandshakeInStream.java b/src/share/classes/sun/security/ssl/HandshakeInStream.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 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
+@@ -190,6 +190,7 @@
+ 
+     byte[] getBytes8() throws IOException {
+         int len = getInt8();
++        verifyLength(len);
+         byte b[] = new byte[len];
+ 
+         read(b, 0, len);
+@@ -198,6 +199,7 @@
+ 
+     byte[] getBytes16() throws IOException {
+         int len = getInt16();
++        verifyLength(len);
+         byte b[] = new byte[len];
+ 
+         read(b, 0, len);
+@@ -206,10 +208,19 @@
+ 
+     byte[] getBytes24() throws IOException {
+         int len = getInt24();
++        verifyLength(len);
+         byte b[] = new byte[len];
+ 
+         read(b, 0, len);
+         return b;
+     }
+ 
++    // Is a length greater than available bytes in the record?
++    private void verifyLength(int len) throws SSLException {
++        if (len > available()) {
++            throw new SSLException(
++                        "Not enough data to fill declared vector size");
++        }
++    }
++
+ }
+diff --git a/src/share/classes/sun/security/ssl/Handshaker.java b/src/share/classes/sun/security/ssl/Handshaker.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 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
+@@ -776,9 +776,9 @@
+             if (debug != null && Debug.isOn("handshake")) {
+                 System.out.println("RSA master secret generation error:");
+                 e.printStackTrace(System.out);
+-                System.out.println("Generating new random premaster secret");
+             }
+-            preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
++            preMasterSecret =
++                    RSAClientKeyExchange.generateDummySecret(protocolVersion);
+             // recursive call with new premaster secret
+             return calculateMasterSecret(preMasterSecret, null);
+         }
+@@ -821,9 +821,9 @@
+             System.out.println("RSA PreMasterSecret version error: expected"
+                 + protocolVersion + " or " + requestedVersion + ", decrypted: "
+                 + premasterVersion);
+-            System.out.println("Generating new random premaster secret");
+         }
+-        preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
++        preMasterSecret =
++                RSAClientKeyExchange.generateDummySecret(protocolVersion);
+         // recursive call with new premaster secret
+         return calculateMasterSecret(preMasterSecret, null);
+     }
+diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 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
+@@ -36,6 +36,7 @@
+ import javax.net.ssl.*;
+ 
+ import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
++import sun.security.util.KeyLength;
+ 
+ /**
+  * This is the client key exchange message (CLIENT --> SERVER) used with
+@@ -85,7 +86,8 @@
+      * it, using its RSA private key.  Result is the same size as the
+      * server's public key, and uses PKCS #1 block format 02.
+      */
+-    RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
++    RSAClientKeyExchange(ProtocolVersion protocolVersion,
++            ProtocolVersion maxVersion,
+             SecureRandom generator, PublicKey publicKey) throws IOException {
+         if (publicKey.getAlgorithm().equals("RSA") == false) {
+             throw new SSLKeyException("Public key not of type RSA");
+@@ -120,7 +122,8 @@
+      * Server gets the PKCS #1 (block format 02) data, decrypts
+      * it with its private key.
+      */
+-    RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
++    RSAClientKeyExchange(ProtocolVersion currentVersion,
++            ProtocolVersion maxVersion, HandshakeInStream input,
+             int messageSize, PrivateKey privateKey) throws IOException {
+ 
+         if (privateKey.getAlgorithm().equals("RSA") == false) {
+@@ -143,28 +146,119 @@
+             cipher.init(Cipher.UNWRAP_MODE, privateKey);
+             preMaster = (SecretKey)cipher.unwrap(encrypted,
+                                 "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
++
++            // polish the premaster secret
++            preMaster = polishPreMasterSecretKey(
++                                currentVersion, maxVersion, preMaster, null);
+         } catch (Exception e) {
+-            /*
+-             * Bogus decrypted ClientKeyExchange? If so, conjure a
+-             * a random preMaster secret that will fail later during
+-             * Finished message processing. This is a countermeasure against
+-             * the "interactive RSA PKCS#1 encryption envelop attack" reported
+-             * in June 1998. Preserving the executation path will
+-             * mitigate timing attacks and force consistent error handling
+-             * that will prevent an attacking client from differentiating
+-             * different kinds of decrypted ClientKeyExchange bogosities.
+-             */
+-            if (debug != null && Debug.isOn("handshake")) {
+-                System.out.println("Error decrypting premaster secret:");
+-                e.printStackTrace(System.out);
+-                System.out.println("Generating random secret");
++            // polish the premaster secret
++            preMaster = polishPreMasterSecretKey(
++                                currentVersion, maxVersion, preMaster, e);
++        }
++    }
++
++    /**
++     * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
++     * treating incorrectly formatted message blocks and/or mismatched
++     * version numbers in a manner indistinguishable from correctly
++     * formatted RSA blocks.
++     *
++     * RFC 5246 describes the approach as :
++     *
++     *  1. Generate a string R of 46 random bytes
++     *
++     *  2. Decrypt the message to recover the plaintext M
++     *
++     *  3. If the PKCS#1 padding is not correct, or the length of message
++     *     M is not exactly 48 bytes:
++     *        pre_master_secret = ClientHello.client_version || R
++     *     else If ClientHello.client_version <= TLS 1.0, and version
++     *     number check is explicitly disabled:
++     *        pre_master_secret = M
++     *     else:
++     *        pre_master_secret = ClientHello.client_version || M[2..47]
++     *
++     * Note that although TLS 1.2 is not supported in this release, we still
++     * want to make use of the above approach to provide better protection.
++     */
++    private SecretKey polishPreMasterSecretKey(
++            ProtocolVersion currentVersion, ProtocolVersion clientHelloVersion,
++            SecretKey secretKey, Exception failoverException) {
++
++        if (failoverException == null && secretKey != null) {
++            // check the length
++            byte[] encoded = secretKey.getEncoded();
++            if (encoded == null) {      // unable to get the encoded key
++                if (debug != null && Debug.isOn("handshake")) {
++                    System.out.println(
++                        "unable to get the plaintext of the premaster secret");
++                }
++
++                int keySize = KeyLength.getKeySize(secretKey);
++                if (keySize > 0 && keySize != 384) {       // 384 = 48 * 8
++                    if (debug != null && Debug.isOn("handshake")) {
++                        System.out.println(
++                            "incorrect length of premaster secret: " +
++                            (keySize/8));
++                    }
++
++                    return generateDummySecret(currentVersion);
++                }
++
++                // The key size is exactly 48 bytes or not accessible.
++                //
++                // Conservatively, pass the checking to master secret
++                // calculation.
++                return secretKey;
++            } else if (encoded.length == 48) {
++                // check the version
++                if (clientHelloVersion.major == encoded[0] &&
++                    clientHelloVersion.minor == encoded[1]) {
++
++                    return secretKey;
++                } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
++                           currentVersion.major == encoded[0] &&
++                           currentVersion.minor == encoded[1]) {
++                    /*
++                     * For compatibility, we maintain the behavior that the
++                     * version in pre_master_secret can be the negotiated
++                     * version for TLS v1.0 and SSL v3.0.
++                     */
++                    return secretKey;
++                }
++
++                if (debug != null && Debug.isOn("handshake")) {
++                    System.out.println("Mismatching Protocol Versions, " +
++                        "ClientHello.client_version is " + clientHelloVersion +
++                        ", while PreMasterSecret.client_version is " +
++                        ProtocolVersion.valueOf(encoded[0], encoded[1]));
++                }
++                return generateDummySecret(currentVersion);
++            } else {
++                if (debug != null && Debug.isOn("handshake")) {
++                    System.out.println(
++                        "incorrect length of premaster secret: " +
++                        encoded.length);
++                }
++                return generateDummySecret(currentVersion);
+             }
+-            preMaster = generateDummySecret(currentVersion);
+         }
++
++        if (debug != null && Debug.isOn("handshake") &&
++                        failoverException != null) {
++            System.out.println("Error decrypting premaster secret:");
++            failoverException.printStackTrace(System.out);
++        }
++
++        return generateDummySecret(currentVersion);
+     }
+ 
+     // generate a premaster secret with the specified version number
+     static SecretKey generateDummySecret(ProtocolVersion version) {
++        if (debug != null && Debug.isOn("handshake")) {
++            System.out.println("Generating a random fake premaster secret");
++        }
++
+         try {
+             KeyGenerator kg =
+                     JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 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
+@@ -190,8 +190,9 @@
+                      * temporary one used for non-export or signing-only
+                      * certificates/keys.
+                      */
+-                    RSAClientKeyExchange pms = new RSAClientKeyExchange
+-                        (protocolVersion, input, message_len, privateKey);
++                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
++                            protocolVersion, clientRequestedVersion,
++                            input, message_len, privateKey);
+                     preMasterSecret = this.clientKeyExchange(pms);
+                     break;
+                 case K_KRB5:
+diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java
+new file mode 100644
+--- /dev/null
++++ openjdk/jdk/src/share/classes/sun/security/util/KeyLength.java
+@@ -0,0 +1,91 @@
++/*
++ * 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.security.util;
++
++import java.security.Key;
++import java.security.PrivilegedAction;
++import java.security.AccessController;
++import java.security.interfaces.ECKey;
++import java.security.interfaces.RSAKey;
++import java.security.interfaces.DSAKey;
++import javax.crypto.SecretKey;
++import javax.crypto.interfaces.DHKey;
++
++/**
++ * A utility class to get key length
++ */
++public final class KeyLength {
++
++    /**
++     * Returns the key size of the given key object in bits.
++     *
++     * @param key the key object, cannot be null
++     * @return the key size of the given key object in bits, or -1 if the
++     *       key size is not accessible
++     */
++    final public static int getKeySize(Key key) {
++        int size = -1;
++
++        if (key instanceof Length) {
++            try {
++                Length ruler = (Length)key;
++                size = ruler.length();
++            } catch (UnsupportedOperationException usoe) {
++                // ignore the exception
++            }
++
++            if (size >= 0) {
++                return size;
++            }
++        }
++
++        // try to parse the length from key specification
++        if (key instanceof SecretKey) {
++            SecretKey sk = (SecretKey)key;
++            String format = sk.getFormat();
++            if ("RAW".equals(format) && sk.getEncoded() != null) {
++                size = (sk.getEncoded().length * 8);
++            }   // Otherwise, it may be a unextractable key of PKCS#11, or
++                // a key we are not able to handle.
++        } else if (key instanceof RSAKey) {
++            RSAKey pubk = (RSAKey)key;
++            size = pubk.getModulus().bitLength();
++        } else if (key instanceof ECKey) {
++            ECKey pubk = (ECKey)key;
++            size = pubk.getParams().getOrder().bitLength();
++        } else if (key instanceof DSAKey) {
++            DSAKey pubk = (DSAKey)key;
++            size = pubk.getParams().getP().bitLength();
++        } else if (key instanceof DHKey) {
++            DHKey pubk = (DHKey)key;
++            size = pubk.getParams().getP().bitLength();
++        }   // Otherwise, it may be a unextractable key of PKCS#11, or
++            // a key we are not able to handle.
++
++        return size;
++    }
++}
++
+diff --git a/src/share/classes/sun/security/util/Length.java b/src/share/classes/sun/security/util/Length.java
+new file mode 100644
+--- /dev/null
++++ openjdk/jdk/src/share/classes/sun/security/util/Length.java
+@@ -0,0 +1,43 @@
++/*
++ * 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.security.util;
++
++/**
++ * The Length interface defines the length of an object
++ */
++public interface Length {
++
++    /**
++     * Gets the length of this object
++     * <p>
++     * Note that if a class of java.security.Key implements this interfaces,
++     * the length should be measured in bits.
++     *
++     * @return the length of this object
++     * @throws UnsupportedOperationException if the operation is not supported
++     */
++    public int length();
++}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7189103.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,39 @@
+# HG changeset patch
+# User coffeys
+# Date 1345121690 -3600
+# Node ID b6a7a661db8a2141ebb2e79ba5739722d1be7bfd
+# Parent  a6294da5a21f609b67a0d4d216028dda9f56e689
+7189103: Executors needs to maintain state
+Reviewed-by: chegar
+
+diff --git a/src/share/classes/java/util/concurrent/Executors.java b/src/share/classes/java/util/concurrent/Executors.java
+--- openjdk/jdk/src/share/classes/java/util/concurrent/Executors.java
++++ openjdk/jdk/src/share/classes/java/util/concurrent/Executors.java
+@@ -530,18 +530,17 @@
+                 return AccessController.doPrivileged(
+                     new PrivilegedExceptionAction<T>() {
+                         public T run() throws Exception {
+-                            ClassLoader savedcl = null;
+                             Thread t = Thread.currentThread();
+-                            try {
+-                                ClassLoader cl = t.getContextClassLoader();
+-                                if (ccl != cl) {
+-                                    t.setContextClassLoader(ccl);
+-                                    savedcl = cl;
++                            ClassLoader cl = t.getContextClassLoader();
++                            if (ccl == cl) {
++                                return task.call();
++                            } else {
++                                t.setContextClassLoader(ccl);
++                                try {
++                                    return task.call();
++                                } finally {
++                                    t.setContextClassLoader(cl);
+                                 }
+-                                return task.call();
+-                            } finally {
+-                                if (savedcl != null)
+-                                    t.setContextClassLoader(savedcl);
+                             }
+                         }
+                     }, acc);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7189490.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,55 @@
+# HG changeset patch
+# User coffeys
+# Date 1345121553 -3600
+# Node ID 7fe230af5036c83eb337b3560821b97c6dec08c9
+# Parent  b6a7a661db8a2141ebb2e79ba5739722d1be7bfd
+7189490: More improvements to DomainCombiner checking
+Reviewed-by: mullan
+
+diff --git a/src/share/classes/java/security/AccessController.java b/src/share/classes/java/security/AccessController.java
+--- openjdk/jdk/src/share/classes/java/security/AccessController.java
++++ openjdk/jdk/src/share/classes/java/security/AccessController.java
+@@ -290,11 +290,11 @@
+      */
+     public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
+ 
+-        DomainCombiner dc = null;
+         AccessControlContext acc = getStackAccessControlContext();
+-        if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
+-            return AccessController.doPrivileged(action, acc);
++        if (acc == null) {
++            return AccessController.doPrivileged(action);
+         }
++        DomainCombiner dc = acc.getAssignedCombiner();
+         return AccessController.doPrivileged(action, preserveCombiner(dc));
+     }
+ 
+@@ -386,11 +386,11 @@
+     public static <T> T doPrivilegedWithCombiner
+         (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
+ 
+-        DomainCombiner dc = null;
+         AccessControlContext acc = getStackAccessControlContext();
+-        if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
+-            return AccessController.doPrivileged(action, acc);
++        if (acc == null) {
++            return AccessController.doPrivileged(action);
+         }
++        DomainCombiner dc = acc.getAssignedCombiner();
+         return AccessController.doPrivileged(action, preserveCombiner(dc));
+     }
+ 
+@@ -417,7 +417,12 @@
+         // perform 'combine' on the caller of doPrivileged,
+         // even if the caller is from the bootclasspath
+         ProtectionDomain[] pds = new ProtectionDomain[] {callerPd};
+-        return new AccessControlContext(combiner.combine(pds, null), combiner);
++        if (combiner == null) {
++            return new AccessControlContext(pds);
++        } else {
++            return new AccessControlContext(combiner.combine(pds, null),
++                                            combiner);
++        }
+     }
+ 
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7189567.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,95 @@
+# HG changeset patch
+# User robm
+# Date 1347900712 -3600
+# Node ID aa1fa3f96d77541a3bafd767001f3100fe6b8a5a
+# Parent  7fe230af5036c83eb337b3560821b97c6dec08c9
+7189567: java net obselete protocol
+Reviewed-by: chegar
+
+diff --git a/src/share/classes/java/net/URL.java b/src/share/classes/java/net/URL.java
+--- openjdk/jdk/src/share/classes/java/net/URL.java
++++ openjdk/jdk/src/share/classes/java/net/URL.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1995, 2007, 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
+@@ -28,6 +28,8 @@
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
++import java.security.AccessController;
++import java.security.PrivilegedAction;
+ import java.util.Hashtable;
+ import java.util.StringTokenizer;
+ import sun.security.util.SecurityConstants;
+@@ -1110,6 +1112,21 @@
+     static Hashtable handlers = new Hashtable();
+     private static Object streamHandlerLock = new Object();
+ 
++    // special case the gopher protocol, disabled by default
++    private static final String GOPHER = "gopher";
++    private static final String ENABLE_GOPHER_PROP = "jdk.net.registerGopherProtocol";
++    private static final boolean enableGopher = AccessController.doPrivileged(
++        new PrivilegedAction<Boolean>() {
++            public Boolean run() {
++                String prop = System.getProperty(ENABLE_GOPHER_PROP);
++                return prop == null ? false :
++                   (prop.equalsIgnoreCase("false") ? false : true);
++             }
++        });
++
++    // package name of the JDK implementation protocol handlers
++    private static final String JDK_PACKAGE_PREFIX =  "sun.net.www.protocol";
++
+     /**
+      * Returns the Stream Handler.
+      * @param protocol the protocol to use
+@@ -1141,7 +1158,7 @@
+ 
+                 // REMIND: decide whether to allow the "null" class prefix
+                 // or not.
+-                packagePrefixList += "sun.net.www.protocol";
++                packagePrefixList += JDK_PACKAGE_PREFIX;
+ 
+                 StringTokenizer packagePrefixIter =
+                     new StringTokenizer(packagePrefixList, "|");
+@@ -1151,6 +1168,15 @@
+ 
+                     String packagePrefix =
+                       packagePrefixIter.nextToken().trim();
++
++                    // do not try to instantiate the JDK gopher handler
++                    // unless the system property had been explicitly set
++                    if (protocol.equalsIgnoreCase(GOPHER) &&
++                        packagePrefix.equals(JDK_PACKAGE_PREFIX) &&
++                        !enableGopher) {
++                            continue;
++                    }
++
+                     try {
+                         String clsName = packagePrefix + "." + protocol +
+                           ".Handler";
+diff --git a/test/java/net/URL/Test.java b/test/java/net/URL/Test.java
+--- openjdk/jdk/test/java/net/URL/Test.java
++++ openjdk/jdk/test/java/net/URL/Test.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -322,10 +322,6 @@
+         test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
+             .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
+ 
+-        test("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles")
+-            .s("gopher").h("spinaltap.micro.umn.edu")
+-            .p("/00/Weather/California/Los%20Angeles").z();
+-
+         test("http://www.math.uio.no/faq/compression-faq/part1.html")
+             .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z();
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7192975.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,35 @@
+# HG changeset patch
+# User asaha
+# Date 1349309813 25200
+# Node ID d77bc9151c1dea1a4a396fb59d58ba7c8d77fd88
+# Parent  aa1fa3f96d77541a3bafd767001f3100fe6b8a5a
+7192975: Conditional usage check is wrong
+Reviewed-by: dsamersoff
+Contributed-by: andreas.eriksson@oracle.com
+
+diff --git a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java
+--- openjdk/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java
++++ openjdk/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -1239,13 +1239,12 @@
+             return s.substring(1, s.length() - 1);
+         }
+         final String className = s.substring(1, slash);
++        
+         final Constructor<?> constr;
+         try {
++            ReflectUtil.checkPackageAccess(className);
+             final ClassLoader contextClassLoader =
+                 Thread.currentThread().getContextClassLoader();
+-            if (contextClassLoader == null) {
+-                ReflectUtil.checkPackageAccess(className);
+-            }
+             final Class<?> c =
+                 Class.forName(className, false, contextClassLoader);
+             constr = c.getConstructor(new Class[] {String.class});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7195194.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,29 @@
+# HG changeset patch
+# User andrew
+# Date 1349974205 -3600
+# Node ID 6a383aef225ab7bb99b723bbb29786e29747a4f0
+# Parent  d77bc9151c1dea1a4a396fb59d58ba7c8d77fd88
+7195194: Better data validation for Swing
+Reviewed-by: art, ahgross
+
+diff --git a/src/share/classes/javax/swing/text/DefaultFormatter.java b/src/share/classes/javax/swing/text/DefaultFormatter.java
+--- openjdk/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java
++++ openjdk/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java
+@@ -24,6 +24,8 @@
+  */
+ package javax.swing.text;
+ 
++import sun.reflect.misc.ConstructorUtil;
++
+ import java.io.Serializable;
+ import java.lang.reflect.*;
+ import java.text.ParseException;
+@@ -245,7 +247,7 @@
+             Constructor cons;
+ 
+             try {
+-                cons = vc.getConstructor(new Class[] { String.class });
++                cons = ConstructorUtil.getConstructor(vc, new Class[]{String.class});
+ 
+             } catch (NoSuchMethodException nsme) {
+                 cons = null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7195917.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,88 @@
+# HG changeset patch
+# User malenkov
+# Date 1348148080 -14400
+# Node ID 074f132d65c91231ca989e4c757207e1cf25a476
+# Parent  6a383aef225ab7bb99b723bbb29786e29747a4f0
+7195917: XMLDecoder parsing at close-time should be improved
+Reviewed-by: art, ahgross
+
+diff --git a/src/share/classes/java/beans/XMLDecoder.java b/src/share/classes/java/beans/XMLDecoder.java
+--- openjdk/jdk/src/share/classes/java/beans/XMLDecoder.java
++++ openjdk/jdk/src/share/classes/java/beans/XMLDecoder.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 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
+@@ -32,6 +32,10 @@
+ import java.lang.ref.Reference;
+ import java.lang.ref.WeakReference;
+ 
++import java.security.AccessControlContext;
++import java.security.AccessController;
++import java.security.PrivilegedAction;
++
+ import org.xml.sax.SAXException;
+ 
+ import javax.xml.parsers.SAXParserFactory;
+@@ -66,6 +70,7 @@
+  * @author Philip Milne
+  */
+ public class XMLDecoder {
++    private final AccessControlContext acc = AccessController.getContext();
+     private InputStream in;
+     private Object owner;
+     private ExceptionListener exceptionListener;
+@@ -248,25 +253,33 @@
+      */
+     private ObjectHandler getHandler() {
+         if ( handler == null ) {
+-            SAXParserFactory factory = SAXParserFactory.newInstance();
+-            try {
+-                SAXParser parser = factory.newSAXParser();
+-                handler = new ObjectHandler( this, getClassLoader() );
+-                parser.parse( in, handler );
++            if ((this.acc == null) && (null != System.getSecurityManager())) {
++                throw new SecurityException("AccessControlContext is not set");
+             }
+-            catch ( ParserConfigurationException e ) {
+-                getExceptionListener().exceptionThrown( e );
+-            }
+-            catch ( SAXException se ) {
+-                Exception e = se.getException();
+-                if ( e == null ) {
+-                    e = se;
++            handler = AccessController.doPrivileged(new PrivilegedAction<ObjectHandler>() {
++                public ObjectHandler run() {
++                    ObjectHandler handler = new ObjectHandler(XMLDecoder.this, getClassLoader());
++                    SAXParserFactory factory = SAXParserFactory.newInstance();
++                    try {
++                        SAXParser parser = factory.newSAXParser();
++                        parser.parse( in, handler );
++                    }
++                    catch ( ParserConfigurationException e ) {
++                        getExceptionListener().exceptionThrown( e );
++                    }
++                    catch ( SAXException se ) {
++                        Exception e = se.getException();
++                        if ( e == null ) {
++                            e = se;
++                        }
++                        getExceptionListener().exceptionThrown( e );
++                    }
++                    catch ( IOException ioe ) {
++                        getExceptionListener().exceptionThrown( ioe );
++                    }
++                    return handler;
+                 }
+-                getExceptionListener().exceptionThrown( e );
+-            }
+-            catch ( IOException ioe ) {
+-                getExceptionListener().exceptionThrown( ioe );
+-            }
++            }, this.acc);
+         }
+         return handler;
+     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7195919.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,63 @@
+# HG changeset patch
+# User dmeetry
+# Date 1347313661 -14400
+# Node ID 5352a40bb0ff7e8a6e826478d7687fff695d9805
+# Parent  074f132d65c91231ca989e4c757207e1cf25a476
+7195919: (sl) ServiceLoader can throw CCE without needing to create instance
+Reviewed-by: smarks
+
+diff --git a/src/share/classes/java/util/ServiceLoader.java b/src/share/classes/java/util/ServiceLoader.java
+--- openjdk/jdk/src/share/classes/java/util/ServiceLoader.java
++++ openjdk/jdk/src/share/classes/java/util/ServiceLoader.java
+@@ -358,14 +358,21 @@
+             }
+             String cn = nextName;
+             nextName = null;
++            Class<?> c = null;
+             try {
+-                S p = service.cast(Class.forName(cn, true, loader)
+-                                   .newInstance());
+-                providers.put(cn, p);
+-                return p;
++                c = Class.forName(cn, false, loader);
+             } catch (ClassNotFoundException x) {
+                 fail(service,
+                      "Provider " + cn + " not found");
++            }
++            if (!service.isAssignableFrom(c)) {
++                fail(service,
++                     "Provider " + cn  + " not a subtype");
++            }
++            try {
++                S p = service.cast(c.newInstance());
++                providers.put(cn, p);
++                return p;
+             } catch (Throwable x) {
+                 fail(service,
+                      "Provider " + cn + " could not be instantiated: " + x,
+diff --git a/src/share/classes/sun/misc/Service.java b/src/share/classes/sun/misc/Service.java
+--- openjdk/jdk/src/share/classes/sun/misc/Service.java
++++ openjdk/jdk/src/share/classes/sun/misc/Service.java
+@@ -284,12 +284,20 @@
+             }
+             String cn = nextName;
+             nextName = null;
++            Class<?> c = null;
+             try {
+-                return Class.forName(cn, true, loader).newInstance();
++                c = Class.forName(cn, false, loader);
+             } catch (ClassNotFoundException x) {
+                 fail(service,
+                      "Provider " + cn + " not found");
+-            } catch (Exception x) {
++            }
++            if (!service.isAssignableFrom(c)) {
++                fail(service,
++                     "Provider " + cn  + " not a subtype");
++            }
++            try {
++                return service.cast(c.newInstance());
++	    } catch (Throwable x) {
+                 fail(service,
+                      "Provider " + cn + " could not be instantiated: " + x,
+                      x);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7198296.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,114 @@
+# HG changeset patch
+# User asaha
+# Date 1349309940 25200
+# Node ID a66bba985c2c46743d6780879278092c0fa5cf2b
+# Parent  5352a40bb0ff7e8a6e826478d7687fff695d9805
+7198296: Refactor classloader usage
+Reviewed-by: dsamersoff
+Contributed-by: andreas.eriksson@oracle.com
+
+diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+--- openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
++++ openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+@@ -165,9 +165,17 @@
+                  withPermissions( new MBeanPermission("*", "getClassLoaderRepository"),
+                                  new RuntimePermission("createClassLoader"))
+             );
+-
+-        serverCommunicatorAdmin = new
+-          RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
++        this.defaultContextClassLoader =
++            AccessController.doPrivileged(
++                new PrivilegedAction<ClassLoader>() {
++                    @Override
++                    public ClassLoader run() {
++                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
++                                dcl);
++                    }
++                });
++        serverCommunicatorAdmin = new 
++            RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
+ 
+         this.env = env;
+     }
+@@ -529,7 +537,7 @@
+                  "connectionId=" + connectionId
+                  +" unwrapping query with defaultClassLoader.");
+ 
+-        queryValue = unwrap(query, defaultClassLoader, QueryExp.class);
++	queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ 
+         try {
+             final Object params[] = new Object[] { name, queryValue };
+@@ -563,7 +571,7 @@
+                  "connectionId=" + connectionId
+                  +" unwrapping query with defaultClassLoader.");
+ 
+-        queryValue = unwrap(query, defaultClassLoader, QueryExp.class);
++	queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ 
+         try {
+             final Object params[] = new Object[] { name, queryValue };
+@@ -1592,7 +1600,8 @@
+             ClassLoader orderCL = AccessController.doPrivileged(
+                 new PrivilegedExceptionAction<ClassLoader>() {
+                     public ClassLoader run() throws Exception {
+-                        return new OrderClassLoaders(cl1, cl2);
++                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
++                                new OrderClassLoaders(cl1, cl2));
+                     }
+                 }
+             );
+@@ -1684,6 +1693,8 @@
+ 
+     private final ClassLoader defaultClassLoader;
+ 
++    private final ClassLoader defaultContextClassLoader;
++
+     private final ClassLoaderWithRepository classLoaderWithRepository;
+ 
+     private boolean terminated = false;
+@@ -1768,4 +1779,43 @@
+ 
+     private static final ClassLogger logger =
+         new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
++    
++    private static final class CombinedClassLoader extends ClassLoader {
++        
++        private final static class ClassLoaderWrapper extends ClassLoader {
++            ClassLoaderWrapper(ClassLoader cl) {
++                super(cl);
++            }
++            
++            @Override
++            protected Class<?> loadClass(String name, boolean resolve) 
++                    throws ClassNotFoundException {
++                return super.loadClass(name, resolve);
++            }
++        };
++        
++        final ClassLoaderWrapper defaultCL;
++        
++        private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) {
++            super(parent);
++            this.defaultCL = new ClassLoaderWrapper(defaultCL);
++        }
++        
++        @Override
++        protected Class<?> loadClass(String name, boolean resolve)
++        throws ClassNotFoundException {
++            try {
++                super.loadClass(name, resolve);
++            } catch(Exception e) {
++                for(Throwable t = e; t != null; t = t.getCause()) {
++                    if(t instanceof SecurityException) {
++                        throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e);
++                    }
++                }
++            }
++            final Class<?> cl = defaultCL.loadClass(name, resolve);
++            return cl;
++        }
++        
++    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/7198606.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,28 @@
+# HG changeset patch
+# User andrew
+# Date 1349974451 -3600
+# Node ID 8319efc7c840d099832e06db7a50dcfb95bfd4aa
+# Parent  a148157cd348fe4c251063db7d3973a83cfcf483
+7198606: Improve VM optimization
+Reviewed-by: roland, twisti
+
+diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
+--- openjdk/hotspot/src/share/vm/opto/loopTransform.cpp
++++ openjdk/hotspot/src/share/vm/opto/loopTransform.cpp
+@@ -2721,6 +2721,8 @@
+   result_mem = new (C, 1) ProjNode(call,TypeFunc::Memory);
+   _igvn.register_new_node_with_optimizer(result_mem);
+ 
++/* Disable following optimization until proper fix (add missing checks).
++
+   // If this fill is tightly coupled to an allocation and overwrites
+   // the whole body, allow it to take over the zeroing.
+   AllocateNode* alloc = AllocateNode::Ideal_allocation(base, this);
+@@ -2744,6 +2746,7 @@
+ #endif
+     }
+   }
++*/
+ 
+   // Redirect the old control and memory edges that are outside the loop.
+   Node* exit = head->loopexit()->proj_out(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/hs20/7158800.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,1413 @@
+# HG changeset patch
+# User kevinw
+# Date 1345802362 -3600
+# Node ID 2faa3f7bad65189e69ab2f9a491743786bb8f07f
+# Parent  a080633e3a056dae9e94077c9ac4cf966137ade9
+7158800: Improve storage of symbol tables
+7178670: runtime/7158800/BadUtf8.java fails in SymbolTable::rehash_table
+7181200: JVM new hashing code breaks SA in product mode
+7190262: Debug builds fail to verify String table with +UseCompressedStrings after 7158800
+Reviewed-by: coleenp
+
+diff --git a/src/share/vm/classfile/altHashing.cpp b/src/share/vm/classfile/altHashing.cpp
+new file mode 100644
+--- /dev/null
++++ openjdk/hotspot/src/share/vm/classfile/altHashing.cpp
+@@ -0,0 +1,304 @@
++/*
++ * 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.
++ *
++ */
++
++#include "precompiled.hpp"
++#include "classfile/altHashing.hpp"
++#include "classfile/symbolTable.hpp"
++#include "classfile/systemDictionary.hpp"
++#include "oops/markOop.hpp"
++#include "runtime/thread.hpp"
++
++// Get the hash code of the classes mirror if it exists, otherwise just
++// return a random number, which is one of the possible hash code used for
++// objects.  We don't want to call the synchronizer hash code to install
++// this value because it may safepoint.
++intptr_t object_hash(klassOop k) {
++  intptr_t hc = Klass::cast(k)->java_mirror()->mark()->hash();
++  return hc != markOopDesc::no_hash ? hc : os::random();
++}
++
++// Seed value used for each alternative hash calculated.
++jint AltHashing::compute_seed() {
++  jlong nanos = os::javaTimeNanos();
++  jlong now = os::javaTimeMillis();
++  jint SEED_MATERIAL[8] = {
++            (jint) object_hash(SystemDictionary::String_klass()),
++            (jint) object_hash(SystemDictionary::System_klass()),
++            (jint) os::random(),  // current thread isn't a java thread
++            (jint) (((julong)nanos) >> 32),
++            (jint) nanos,
++            (jint) (((julong)now) >> 32),
++            (jint) now,
++            (jint) (os::javaTimeNanos() >> 2)
++  };
++
++  return murmur3_32(SEED_MATERIAL, 8);
++}
++
++
++// Murmur3 hashing for Symbol
++jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) {
++  jint h1 = seed;
++  int count = len;
++  int offset = 0;
++
++  // body
++  while (count >= 4) {
++    jint 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) {
++    jint 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 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Murmur3 hashing for Strings
++jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int count = len;
++
++  // body
++  while (count >= 2) {
++    jchar d1 = data[off++] & 0xFFFF;
++    jchar d2 = data[off++];
++    jint k1 = (d1 | d2 << 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 * 2; // (Character.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Hash used for the seed.
++jint AltHashing::murmur3_32(jint seed, const int* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int end = len;
++
++  // body
++  while (off < end) {
++    jint 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 * 4; // (Integer.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((juint)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((juint)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((juint)h1) >> 16;
++
++  return h1;
++}
++
++jint AltHashing::murmur3_32(const int* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++#ifndef PRODUCT
++// Overloaded versions for internal test.
++jint AltHashing::murmur3_32(const jbyte* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++jint AltHashing::murmur3_32(const jchar* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++// Internal test for alternate hashing.  Translated from JDK version
++// test/sun/misc/Hashing.java
++static const jbyte ONE_BYTE[] = { (jbyte) 0x80};
++static const jbyte TWO_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81};
++static const jchar ONE_CHAR[] = { (jchar) 0x8180};
++static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82};
++static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83};
++static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382};
++static const jint ONE_INT[] = { 0x83828180};
++static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85};
++static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584};
++static const jbyte EIGHT_BYTE[] = {
++  (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82,
++  (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85,
++  (jbyte) 0x86, (jbyte) 0x87};
++static const jchar FOUR_CHAR[] = {
++  (jchar) 0x8180, (jchar) 0x8382,
++  (jchar) 0x8584, (jchar) 0x8786};
++
++static const jint TWO_INT[] = { 0x83828180, 0x87868584};
++
++static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;
++
++void AltHashing::testMurmur3_32_ByteArray() {
++  // printf("testMurmur3_32_ByteArray\n");
++
++  jbyte* vector = new jbyte[256];
++  jbyte* hashes = new jbyte[4 * 256];
++
++  for (int i = 0; i < 256; i++) {
++    vector[i] = (jbyte) i;
++  }
++
++  // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
++  for (int i = 0; i < 256; i++) {
++    jint hash = murmur3_32(256 - i, vector, i);
++    hashes[i * 4] = (jbyte) hash;
++    hashes[i * 4 + 1] = (jbyte) (((juint)hash) >> 8);
++    hashes[i * 4 + 2] = (jbyte) (((juint)hash) >> 16);
++    hashes[i * 4 + 3] = (jbyte) (((juint)hash) >> 24);
++  }
++
++  // hash to get const result.
++  juint final_hash = murmur3_32(hashes, 4*256);
++
++  assert (MURMUR3_32_X86_CHECK_VALUE == final_hash,
++    err_msg(
++        "Calculated hash result not as expected. Expected %08X got %08X\n",
++        MURMUR3_32_X86_CHECK_VALUE,
++        final_hash));
++}
++
++void AltHashing::testEquivalentHashes() {
++  jint jbytes, jchars, ints;
++
++  // printf("testEquivalentHashes\n");
++
++  jbytes = murmur3_32(TWO_BYTE, 2);
++  jchars = murmur3_32(ONE_CHAR, 1);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(FOUR_BYTE, 4);
++  jchars = murmur3_32(TWO_CHAR, 2);
++  ints = murmur3_32(ONE_INT, 1);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++
++  jbytes = murmur3_32(SIX_BYTE, 6);
++  jchars = murmur3_32(THREE_CHAR, 3);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(EIGHT_BYTE, 8);
++  jchars = murmur3_32(FOUR_CHAR, 4);
++  ints = murmur3_32(TWO_INT, 2);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++}
++
++// Returns true if the alternate hashcode is correct
++void AltHashing::test_alt_hash() {
++  testMurmur3_32_ByteArray();
++  testEquivalentHashes();
++}
++#endif // PRODUCT
+diff --git a/src/share/vm/classfile/altHashing.hpp b/src/share/vm/classfile/altHashing.hpp
+new file mode 100644
+--- /dev/null
++++ openjdk/hotspot/src/share/vm/classfile/altHashing.hpp
+@@ -0,0 +1,62 @@
++/*
++ * 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.
++ *
++ */
++
++#ifndef SHARE_VM_CLASSFILE_ALTHASHING_HPP
++#define SHARE_VM_CLASSFILE_ALTHASHING_HPP
++
++#include "prims/jni.h"
++#include "classfile/symbolTable.hpp"
++
++/**
++ * Hashing utilities.
++ *
++ * Implementation of Murmur3 hashing.
++ * This code was translated from src/share/classes/sun/misc/Hashing.java
++ * code in the JDK.
++ */
++
++class AltHashing : AllStatic {
++
++  // utility function copied from java/lang/Integer
++  static jint Integer_rotateLeft(jint i, int distance) {
++    return (i << distance) | (((juint)i) >> (32-distance));
++  }
++  static jint murmur3_32(const int* data, int len);
++  static jint murmur3_32(jint seed, const int* data, int len);
++
++#ifndef PRODUCT
++  // Hashing functions used for internal testing
++  static jint murmur3_32(const jbyte* data, int len);
++  static jint murmur3_32(const jchar* data, int len);
++  static void testMurmur3_32_ByteArray();
++  static void testEquivalentHashes();
++#endif // PRODUCT
++
++ public:
++  static jint compute_seed();
++  static jint murmur3_32(jint seed, const jbyte* data, int len);
++  static jint murmur3_32(jint seed, const jchar* data, int len);
++  NOT_PRODUCT(static void test_alt_hash();)
++};
++#endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP
+diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
+--- openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp
++++ openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp
+@@ -278,6 +278,28 @@
+   return result;
+ }
+ 
++unsigned int java_lang_String::to_hash(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string will hash to zero with String.toHash() function.
++  if (length == 0) return 0;
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return java_lang_String::to_hash(value->char_at_addr(offset), length);
++}
++
++unsigned int java_lang_String::hash_string(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string doesn't hash necessarily hash to zero.
++  if (length == 0) {
++    return StringTable::hash_string(NULL, 0);
++  }
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return StringTable::hash_string(value->char_at_addr(offset), length);
++}
++
+ symbolHandle java_lang_String::as_symbol(Handle java_string, TRAPS) {
+   oop          obj    = java_string();
+   typeArrayOop value  = java_lang_String::value(obj);
+diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
+--- openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp
++++ openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp
+@@ -109,6 +109,30 @@
+   static char*  as_platform_dependent_str(Handle java_string, TRAPS);
+   static jchar* as_unicode_string(oop java_string, int& length);
+ 
++  // Compute the hash value for a java.lang.String object which would
++  // contain the characters passed in.
++  //
++  // As the hash value used by the String object itself, in
++  // String.hashCode().  This value is normally calculated in Java code
++  // in the String.hashCode method(), but is precomputed for String
++  // objects in the shared archive file.
++  // hash P(31) from Kernighan & Ritchie
++  //
++  // For this reason, THIS ALGORITHM MUST MATCH String.toHash().
++  template <typename T> static unsigned int to_hash(T* s, int len) {
++    unsigned int h = 0;
++    while (len-- > 0) {
++      h = 31*h + (unsigned int) *s;
++      s++;
++    }
++    return h;
++  }
++  static unsigned int to_hash(oop java_string);
++
++  // This is the string hash code used by the StringTable, which may be
++  // the same as String.toHash or an alternate hash code.
++  static unsigned int hash_string(oop java_string);
++
+   static bool equals(oop java_string, jchar* chars, int len);
+ 
+   // Conversion between '.' and '/' formats
+diff --git a/src/share/vm/classfile/symbolTable.cpp b/src/share/vm/classfile/symbolTable.cpp
+--- openjdk/hotspot/src/share/vm/classfile/symbolTable.cpp
++++ openjdk/hotspot/src/share/vm/classfile/symbolTable.cpp
+@@ -23,6 +23,7 @@
+  */
+ 
+ #include "precompiled.hpp"
++#include "classfile/altHashing.hpp"
+ #include "classfile/javaClasses.hpp"
+ #include "classfile/symbolTable.hpp"
+ #include "classfile/systemDictionary.hpp"
+@@ -34,16 +35,40 @@
+ #include "oops/symbolKlass.hpp"
+ #include "runtime/mutexLocker.hpp"
+ #include "utilities/hashtable.inline.hpp"
++#include "utilities/numberSeq.hpp"
+ 
+ // --------------------------------------------------------------------------
+ 
+ SymbolTable* SymbolTable::_the_table = NULL;
++bool SymbolTable::_needs_rehashing = false;
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing strings.   Set flag to use the alternate hash code afterwards.
++void SymbolTable::rehash_table() {
++
++  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
++  // This should never happen with -Xshare:dump but it might in testing mode.
++  if (DumpSharedSpaces) return;
++  // Create a new symbol table
++  SymbolTable* new_table = new SymbolTable();
++
++  the_table()->move_to(new_table);
++
++  // Delete the table and buckets (entries are reused in new table).
++  delete _the_table;
++  // Don't check if we need rehashing until the table gets unbalanced again.
++  // Then rehash with a new global seed.
++  _needs_rehashing = false;
++  _the_table = new_table;
++}
+ 
+ // Lookup a symbol in a bucket.
+ 
+ symbolOop SymbolTable::lookup(int index, const char* name,
+                               int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
++    count++;
+     if (e->hash() == hash) {
+       symbolOop sym = symbolOop(e->literal());
+       if (sym->equals(name, len)) {
+@@ -51,9 +76,20 @@
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
++// Pick hashing algorithm.
++unsigned int SymbolTable::hash_symbol(const char* s, int len) {
++  return the_table()->use_alternate_hashcode() ?
++           AltHashing::murmur3_32(the_table()->seed(), (const jbyte*)s, len) :
++           java_lang_String::to_hash(s, len);
++}
++
+ 
+ // We take care not to be blocking while holding the
+ // SymbolTable_lock. Otherwise, the system might deadlock, since the
+@@ -71,8 +107,17 @@
+   // Found
+   if (s != NULL) return s;
+ 
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)name, len, CHECK_NULL);
++  symbolHandle sym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
+   // Otherwise, add to symbol to table
+-  return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL);
++  return the_table()->basic_add(sym, index, (u1*)name, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) {
+@@ -108,7 +153,16 @@
+   // We can't include the code in No_Safepoint_Verifier because of the
+   // ResourceMark.
+ 
+-  return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL);
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)buffer, len, CHECK_NULL);
++  symbolHandle newsym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
++  return the_table()->basic_add(newsym, index, (u1*)buffer, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup_only(const char* name, int len,
+@@ -156,36 +210,68 @@
+ void SymbolTable::add(constantPoolHandle cp, int names_count,
+                       const char** names, int* lengths, int* cp_indices,
+                       unsigned int* hashValues, TRAPS) {
+-  SymbolTable* table = the_table();
+-  bool added = table->basic_add(cp, names_count, names, lengths,
+-                                cp_indices, hashValues, CHECK);
+-  if (!added) {
++
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop sym_oops[symbol_alloc_batch_size];
++  bool allocated = sk->allocate_symbols(names_count, names, lengths,
++                                        sym_oops, CHECK);
++  if (!allocated) {
+     // do it the hard way
+     for (int i=0; i<names_count; i++) {
++      assert(!Universe::heap()->is_in_reserved(names[i]) || GC_locker::is_active(),
++         "proposed name of symbol must be stable");
++
++      // We assume that lookup() has been called already, that it failed,
++      // and symbol was not found.  We create the symbol here.
++      symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++      symbolOop s_oop = sk->allocate_symbol((u1*)names[i], lengths[i], CHECK);
++      symbolHandle sym (THREAD, s_oop);
++
++      // Allocation must be done before grabbing the SymbolTable_lock lock
++      MutexLocker ml(SymbolTable_lock, THREAD);
++
++      SymbolTable* table = the_table();
+       int index = table->hash_to_index(hashValues[i]);
+-      symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i],
++      symbolOop s = table->basic_add(sym, index, (u1*)names[i], lengths[i],
+                                        hashValues[i], CHECK);
+-      cp->symbol_at_put(cp_indices[i], sym);
++      cp->symbol_at_put(cp_indices[i], s);
+     }
++    return;
+   }
++
++  symbolHandle syms[symbol_alloc_batch_size];
++  for (int i=0; i<names_count; i++) {
++    syms[i] = symbolHandle(THREAD, sym_oops[i]);
++  }
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
++  SymbolTable* table = the_table();
++  bool added = table->basic_add(syms, cp, names_count, names, lengths,
++                                cp_indices, hashValues, CHECK);
++  assert(added, "should always return true");
+ }
+ 
+-symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
+-                                 unsigned int hashValue, TRAPS) {
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
+-
+-  // We assume that lookup() has been called already, that it failed,
+-  // and symbol was not found.  We create the symbol here.
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL);
+-  symbolHandle sym (THREAD, s_oop);
+-
+-  // Allocation must be done before grapping the SymbolTable_lock lock
+-  MutexLocker ml(SymbolTable_lock, THREAD);
++symbolOop SymbolTable::basic_add(symbolHandle sym, int index_arg, u1 *name, int len,
++                                 unsigned int hashValue_arg, TRAPS) {
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+   assert(sym->equals((char*)name, len), "symbol must be properly initialized");
+ 
++  // Check if the symbol table has been rehashed, if so, need to recalculate
++  // the hash value and index.
++  unsigned int hashValue;
++  int index;
++  if (use_alternate_hashcode()) {
++    hashValue = hash_symbol((const char*)name, len);
++    index = hash_to_index(hashValue);
++  } else {
++    hashValue = hashValue_arg;
++    index = index_arg;
++  }
++
+   // Since look-up was done lock-free, we need to check if another
+   // thread beat us in the race to insert the symbol.
+ 
+@@ -201,48 +287,42 @@
+   return sym();
+ }
+ 
+-bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
++bool SymbolTable::basic_add(symbolHandle* syms,
++                            constantPoolHandle cp, int names_count,
+                             const char** names, int* lengths,
+                             int* cp_indices, unsigned int* hashValues,
+                             TRAPS) {
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop sym_oops[symbol_alloc_batch_size];
+-  bool allocated = sk->allocate_symbols(names_count, names, lengths,
+-                                        sym_oops, CHECK_false);
+-  if (!allocated) {
+-    return false;
+-  }
+-  symbolHandle syms[symbol_alloc_batch_size];
+-  int i;
+-  for (i=0; i<names_count; i++) {
+-    syms[i] = symbolHandle(THREAD, sym_oops[i]);
+-  }
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+-  // Allocation must be done before grabbing the SymbolTable_lock lock
+-  MutexLocker ml(SymbolTable_lock, THREAD);
+-
+-  for (i=0; i<names_count; i++) {
++  for (int i=0; i<names_count; i++) {
+     assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
++    // Check if the symbol table has been rehashed, if so, need to recalculate
++    // the hash value.
++    unsigned int hashValue;
++    if (use_alternate_hashcode()) {
++      hashValue = hash_symbol(names[i], lengths[i]);
++    } else {
++      hashValue = hashValues[i];
++    }
+     // Since look-up was done lock-free, we need to check if another
+     // thread beat us in the race to insert the symbol.
+-    int index = hash_to_index(hashValues[i]);
+-    symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]);
++    int index = hash_to_index(hashValue);
++    symbolOop test = lookup(index, names[i], lengths[i], hashValue);
+     if (test != NULL) {
+       // A race occurred and another thread introduced the symbol, this one
+       // will be dropped and collected. Use test instead.
+       cp->symbol_at_put(cp_indices[i], test);
+     } else {
+       symbolOop sym = syms[i]();
+-      HashtableEntry* entry = new_entry(hashValues[i], sym);
++      HashtableEntry* entry = new_entry(hashValue, sym);
+       add_entry(index, entry);
+       cp->symbol_at_put(cp_indices[i], sym);
+     }
+   }
+-
+-  return true;
++  return true;  // always returns true
+ }
+ 
+-
+ void SymbolTable::verify() {
+   for (int i = 0; i < the_table()->table_size(); ++i) {
+     HashtableEntry* p = the_table()->bucket(i);
+@@ -251,7 +331,7 @@
+       guarantee(s != NULL, "symbol is NULL");
+       s->verify();
+       guarantee(s->is_perm(), "symbol not in permspace");
+-      unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
++      unsigned int h = hash_symbol((const char*)s->bytes(), s->utf8_length());
+       guarantee(p->hash() == h, "broken hash in symbol table entry");
+       guarantee(the_table()->hash_to_index(h) == i,
+                 "wrong index in symbol table");
+@@ -259,6 +339,23 @@
+   }
+ }
+ 
++void SymbolTable::dump(outputStream* st) {
++  NumberSeq summary;
++  for (int i = 0; i < the_table()->table_size(); ++i) {
++    int count = 0;
++    for (HashtableEntry* e = the_table()->bucket(i);
++       e != NULL; e = e->next()) {
++      count++;
++    }
++    summary.add((double)count);
++  }
++  st->print_cr("SymbolTable statistics:");
++  st->print_cr("Number of buckets       : %7d", summary.num());
++  st->print_cr("Average bucket size     : %7.0f", summary.avg());
++  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
++  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
++  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
++}
+ 
+ //---------------------------------------------------------------------------
+ // Non-product code
+@@ -321,7 +418,6 @@
+   tty->print_cr(" %s %d: %d\n", "Number chains longer than",
+                     results_length, out_of_range);
+ }
+-
+ #endif // PRODUCT
+ 
+ // --------------------------------------------------------------------------
+@@ -367,66 +463,56 @@
+ // --------------------------------------------------------------------------
+ 
+ 
+-// Compute the hash value for a java.lang.String object which would
+-// contain the characters passed in. This hash value is used for at
+-// least two purposes.
+-//
+-// (a) As the hash value used by the StringTable for bucket selection
+-//     and comparison (stored in the HashtableEntry structures).  This
+-//     is used in the String.intern() method.
+-//
+-// (b) As the hash value used by the String object itself, in
+-//     String.hashCode().  This value is normally calculate in Java code
+-//     in the String.hashCode method(), but is precomputed for String
+-//     objects in the shared archive file.
+-//
+-//     For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
++StringTable* StringTable::_the_table = NULL;
+ 
+-int StringTable::hash_string(jchar* s, int len) {
+-  unsigned h = 0;
+-  while (len-- > 0) {
+-    h = 31*h + (unsigned) *s;
+-    s++;
+-  }
+-  return h;
++bool StringTable::_needs_rehashing = false;
++
++// Pick hashing algorithm
++unsigned int StringTable::hash_string(const jchar* s, int len) {
++  return the_table()->use_alternate_hashcode() ? AltHashing::murmur3_32(the_table()->seed(), s, len) :
++                                    java_lang_String::to_hash(s, len);
+ }
+ 
+-
+-StringTable* StringTable::_the_table = NULL;
+-
+ oop StringTable::lookup(int index, jchar* name,
+                         int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) {
++    count++;
+     if (l->hash() == hash) {
+       if (java_lang_String::equals(l->literal(), name, len)) {
+         return l->literal();
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
+ 
+-oop StringTable::basic_add(int index, Handle string_or_null, jchar* name,
+-                           int len, unsigned int hashValue, TRAPS) {
+-  debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
++oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
++                           int len, unsigned int hashValue_arg, TRAPS) {
+ 
+-  Handle string;
+-  // try to reuse the string if possible
+-  if (!string_or_null.is_null() && string_or_null()->is_perm()) {
+-    string = string_or_null;
+-  } else {
+-    string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
+-  }
+-
+-  // Allocation must be done before grapping the SymbolTable_lock lock
+-  MutexLocker ml(StringTable_lock, THREAD);
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+   assert(java_lang_String::equals(string(), name, len),
+          "string must be properly initialized");
+ 
++  // Check if the symbol table has been rehashed, if so, need to recalculate
++  // the hash value and index before second lookup.
++  unsigned int hashValue;
++  int index;
++  if (use_alternate_hashcode()) {
++    hashValue = hash_string(name, len);
++    index = hash_to_index(hashValue);
++  } else {
++    hashValue = hashValue_arg;
++    index = index_arg;
++  }
++
+   // Since look-up was done lock-free, we need to check if another
+   // thread beat us in the race to insert the symbol.
+ 
+@@ -456,13 +542,28 @@
+                         int len, TRAPS) {
+   unsigned int hashValue = hash_string(name, len);
+   int index = the_table()->hash_to_index(hashValue);
+-  oop string = the_table()->lookup(index, name, len, hashValue);
++  oop found_string = the_table()->lookup(index, name, len, hashValue);
+ 
+   // Found
+-  if (string != NULL) return string;
++  if (found_string != NULL) return found_string;
++
++  debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
++  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
++         "proposed name of symbol must be stable");
++
++  Handle string;
++  // try to reuse the string if possible
++  if (!string_or_null.is_null() && string_or_null()->is_perm()) {
++    string = string_or_null;
++  } else {
++    string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
++  }
++
++  // Allocation must be done before grabbing the StringTable_lock lock
++  MutexLocker ml(StringTable_lock, THREAD);
+ 
+   // Otherwise, add to symbol to table
+-  return the_table()->basic_add(index, string_or_null, name, len,
++  return the_table()->basic_add(index, string, name, len,
+                                 hashValue, CHECK_NULL);
+ }
+ 
+@@ -517,3 +618,41 @@
+     }
+   }
+ }
++
++void StringTable::dump(outputStream* st) {
++  NumberSeq summary;
++  for (int i = 0; i < the_table()->table_size(); ++i) {
++    HashtableEntry* p = the_table()->bucket(i);
++    int count = 0;
++    for ( ; p != NULL; p = p->next()) {
++      count++;
++    }
++    summary.add((double)count);
++  }
++  st->print_cr("StringTable statistics:");
++  st->print_cr("Number of buckets       : %7d", summary.num());
++  st->print_cr("Average bucket size     : %7.0f", summary.avg());
++  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
++  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
++  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
++}
++
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing strings.   Set flag to use the alternate hash code afterwards.
++void StringTable::rehash_table() {
++  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
++  // This should never happen with -Xshare:dump but it might in testing mode.
++  if (DumpSharedSpaces) return;
++  StringTable* new_table = new StringTable();
++
++  // Rehash the table
++  the_table()->move_to(new_table);
++
++  // Delete the table and buckets (entries are reused in new table).
++  delete _the_table;
++  // Don't check if we need rehashing until the table gets unbalanced again.
++  // Then rehash with a new global seed.
++  _needs_rehashing = false;
++  _the_table = new_table;
++}
+diff --git a/src/share/vm/classfile/symbolTable.hpp b/src/share/vm/classfile/symbolTable.hpp
+--- openjdk/hotspot/src/share/vm/classfile/symbolTable.hpp
++++ openjdk/hotspot/src/share/vm/classfile/symbolTable.hpp
+@@ -40,6 +40,7 @@
+ //  - symbolTableEntrys are allocated in blocks to reduce the space overhead.
+ 
+ class BoolObjectClosure;
++class outputStream;
+ 
+ 
+ class SymbolTable : public Hashtable {
+@@ -49,10 +50,13 @@
+   // The symbol table
+   static SymbolTable* _the_table;
+ 
++  // Set if one bucket is out of balance due to hash algorithm deficiency
++  static bool _needs_rehashing;
++
+   // Adding elements
+-  symbolOop basic_add(int index, u1* name, int len,
++  symbolOop basic_add(symbolHandle sym, int index, u1* name, int len,
+                       unsigned int hashValue, TRAPS);
+-  bool basic_add(constantPoolHandle cp, int names_count,
++  bool basic_add(symbolHandle* syms, constantPoolHandle cp, int names_count,
+                  const char** names, int* lengths, int* cp_indices,
+                  unsigned int* hashValues, TRAPS);
+ 
+@@ -61,6 +65,8 @@
+     symbol_table_size = 20011
+   };
+ 
++  static unsigned int hash_symbol(const char* s, int len);
++
+   symbolOop lookup(int index, const char* name, int len, unsigned int hash);
+ 
+   SymbolTable()
+@@ -70,7 +76,6 @@
+     : Hashtable(symbol_table_size, sizeof (HashtableEntry), t,
+                 number_of_entries) {}
+ 
+-
+ public:
+   enum {
+     symbol_alloc_batch_size = 8
+@@ -137,6 +142,7 @@
+ 
+   // Debugging
+   static void verify();
++  static void dump(outputStream* st);
+ 
+   // Sharing
+   static void copy_buckets(char** top, char*end) {
+@@ -148,6 +154,10 @@
+   static void reverse(void* boundary = NULL) {
+     ((Hashtable*)the_table())->reverse(boundary);
+   }
++
++  // Rehash the symbol table if it gets out of balance
++  static void rehash_table();
++  static bool needs_rehashing()         { return _needs_rehashing; }
+ };
+ 
+ 
+@@ -158,8 +168,11 @@
+   // The string table
+   static StringTable* _the_table;
+ 
++  // Set if one bucket is out of balance due to hash algorithm deficiency
++  static bool _needs_rehashing;
++
+   static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
+-  oop basic_add(int index, Handle string_or_null, jchar* name, int len,
++  oop basic_add(int index, Handle string, jchar* name, int len,
+                 unsigned int hashValue, TRAPS);
+ 
+   // Table size
+@@ -192,10 +205,6 @@
+     _the_table = new StringTable(t, number_of_entries);
+   }
+ 
+-
+-  static int hash_string(jchar* s, int len);
+-
+-
+   // GC support
+   //   Delete pointers to otherwise-unreachable objects.
+   static void unlink(BoolObjectClosure* cl) {
+@@ -207,6 +216,14 @@
+     the_table()->Hashtable::oops_do(f);
+   }
+ 
++  // Hashing algorithm, used as the hash value used by the
++  //     StringTable for bucket selection and comparison (stored in the
++  //     HashtableEntry structures).  This is used in the String.intern() method.
++  static unsigned int hash_string(const jchar* s, int len);
++
++  // Internal test.
++  static void test_alt_hash() PRODUCT_RETURN;
++
+   // Probing
+   static oop lookup(symbolOop symbol);
+ 
+@@ -217,6 +234,7 @@
+ 
+   // Debugging
+   static void verify();
++  static void dump(outputStream* st);
+ 
+   // Sharing
+   static void copy_buckets(char** top, char*end) {
+@@ -228,6 +246,9 @@
+   static void reverse() {
+     ((BasicHashtable*)the_table())->reverse();
+   }
++
++  // Rehash the symbol table if it gets out of balance
++  static void rehash_table();
++  static bool needs_rehashing() { return _needs_rehashing; }
+ };
+-
+ #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
+diff --git a/src/share/vm/memory/dump.cpp b/src/share/vm/memory/dump.cpp
+--- openjdk/hotspot/src/share/vm/memory/dump.cpp
++++ openjdk/hotspot/src/share/vm/memory/dump.cpp
+@@ -62,8 +62,8 @@
+ // written later, increasing the likelihood that the shared page contain
+ // the hash can be shared.
+ //
+-// NOTE THAT the algorithm in StringTable::hash_string() MUST MATCH the
+-// algorithm in java.lang.String.hashCode().
++// NOTE THAT we have to call java_lang_String::to_hash() to match the
++// algorithm in java.lang.String.toHash().
+ 
+ class StringHashCodeClosure: public OopClosure {
+ private:
+@@ -88,7 +88,7 @@
+         } else {
+           int offset = java_lang_String::offset(obj);
+           jchar* s = value->char_at_addr(offset);
+-          hash = StringTable::hash_string(s, length);
++          hash = java_lang_String::to_hash(s, length);
+         }
+         obj->int_field_put(hash_offset, hash);
+       }
+diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
+--- openjdk/hotspot/src/share/vm/runtime/globals.hpp
++++ openjdk/hotspot/src/share/vm/runtime/globals.hpp
+@@ -2511,6 +2511,9 @@
+   product(bool, UseHeavyMonitors, false,                                    \
+           "use heavyweight instead of lightweight Java monitors")           \
+                                                                             \
++  product(bool, PrintStringTableStatistics, false,                          \
++          "print statistics about the StringTable and SymbolTable")         \
++                                                                            \
+   notproduct(bool, PrintSymbolTableSizeHistogram, false,                    \
+           "print histogram of the symbol table")                            \
+                                                                             \
+diff --git a/src/share/vm/runtime/init.cpp b/src/share/vm/runtime/init.cpp
+--- openjdk/hotspot/src/share/vm/runtime/init.cpp
++++ openjdk/hotspot/src/share/vm/runtime/init.cpp
+@@ -23,6 +23,7 @@
+  */
+ 
+ #include "precompiled.hpp"
++#include "classfile/symbolTable.hpp"
+ #include "code/icBuffer.hpp"
+ #include "gc_interface/collectedHeap.hpp"
+ #include "interpreter/bytecodes.hpp"
+@@ -153,6 +154,10 @@
+       // Print the collected safepoint statistics.
+       SafepointSynchronize::print_stat_on_exit();
+     }
++    if (PrintStringTableStatistics) {
++      SymbolTable::dump(tty);
++      StringTable::dump(tty);
++    }
+     ostream_exit();
+   }
+ }
+diff --git a/src/share/vm/runtime/safepoint.cpp b/src/share/vm/runtime/safepoint.cpp
+--- openjdk/hotspot/src/share/vm/runtime/safepoint.cpp
++++ openjdk/hotspot/src/share/vm/runtime/safepoint.cpp
+@@ -23,6 +23,7 @@
+  */
+ 
+ #include "precompiled.hpp"
++#include "classfile/symbolTable.hpp"
+ #include "classfile/systemDictionary.hpp"
+ #include "code/codeCache.hpp"
+ #include "code/icBuffer.hpp"
+@@ -501,8 +502,20 @@
+     CompilationPolicy::policy()->do_safepoint_work();
+   }
+ 
+-  TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime);
+-  NMethodSweeper::scan_stacks();
++  {
++    TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime);
++    NMethodSweeper::scan_stacks();
++  }
++
++  if (SymbolTable::needs_rehashing()) {
++    TraceTime t5("rehashing symbol table", TraceSafepointCleanupTime);
++    SymbolTable::rehash_table();
++  }
++
++  if (StringTable::needs_rehashing()) {
++    TraceTime t6("rehashing string table", TraceSafepointCleanupTime);
++    StringTable::rehash_table();
++  }
+ }
+ 
+ 
+diff --git a/src/share/vm/utilities/hashtable.cpp b/src/share/vm/utilities/hashtable.cpp
+--- openjdk/hotspot/src/share/vm/utilities/hashtable.cpp
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.cpp
+@@ -1,5 +1,4 @@
+-/*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++/* * Copyright (c) 2003, 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
+@@ -23,7 +22,10 @@
+  */
+ 
+ #include "precompiled.hpp"
++#include "classfile/altHashing.hpp"
++#include "classfile/javaClasses.hpp"
+ #include "memory/allocation.inline.hpp"
++#include "memory/filemap.hpp"
+ #include "memory/resourceArea.hpp"
+ #include "oops/oop.inline.hpp"
+ #include "runtime/safepoint.hpp"
+@@ -69,7 +71,6 @@
+ 
+ HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) {
+   HashtableEntry* entry;
+-
+   entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue);
+   entry->set_literal(obj);   // clears literal string field
+   HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
+@@ -85,18 +86,24 @@
+   // entries at a safepoint.
+   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+   for (int i = 0; i < table_size(); ++i) {
+-    for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) {
+-      HashtableEntry* entry = *p;
+-      if (entry->is_shared()) {
++    HashtableEntry** p = bucket_addr(i);
++    HashtableEntry* entry = bucket(i);
++    while (entry != NULL) {
++      // Shared entries are normally at the end of the bucket and if we run into
++      // a shared entry, then there is nothing more to remove. However, if we
++      // have rehashed the table, then the shared entries are no longer at the
++      // end of the bucket.
++      if (entry->is_shared() && !use_alternate_hashcode()) {
+         break;
+       }
+       assert(entry->literal() != NULL, "just checking");
+-      if (is_alive->do_object_b(entry->literal())) {
++      if (entry->is_shared() || is_alive->do_object_b(entry->literal())) {
+         p = entry->next_addr();
+       } else {
+         *p = entry->next();
+         free_entry(entry);
+       }
++      entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
+     }
+   }
+ }
+@@ -123,6 +130,96 @@
+ }
+ 
+ 
++// Check to see if the hashtable is unbalanced.  The caller set a flag to
++// rehash at the next safepoint.  If this bucket is 60 times greater than the
++// expected average bucket length, it's an unbalanced hashtable.
++// This is somewhat an arbitrary heuristic but if one bucket gets to
++// rehash_count which is currently 100, there's probably something wrong.
++
++bool BasicHashtable::check_rehash_table(int count) {
++  assert(table_size() != 0, "underflow");
++  if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
++    // Set a flag for the next safepoint, which should be at some guaranteed
++    // safepoint interval.
++    return true;
++  }
++  return false;
++}
++
++unsigned int Hashtable::new_hash(oop string) {
++  ResourceMark rm;
++  int length;
++  if (java_lang_String::is_instance(string)) {
++    jchar* chars = java_lang_String::as_unicode_string(string, length);
++    // Use alternate hashing algorithm on the string
++    return AltHashing::murmur3_32(seed(), chars, length);
++  } else {
++    // Use alternate hashing algorithm on this symbol.
++    symbolOop symOop = (symbolOop) string;
++    return AltHashing::murmur3_32(seed(), (const jbyte*)symOop->bytes(), symOop->utf8_length());
++  }
++}
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing elements.   This can be used to change the hash code
++// and could in the future change the size of the table.
++
++void Hashtable::move_to(Hashtable* new_table) {
++  // Initialize the global seed for hashing.
++  assert(new_table->seed() == 0, "should be zero");
++  _seed = AltHashing::compute_seed();
++  assert(seed() != 0, "shouldn't be zero");
++  new_table->set_seed(_seed);
++
++  int saved_entry_count = this->number_of_entries();
++  
++  // Iterate through the table and create a new entry for the new table
++  for (int i = 0; i < new_table->table_size(); ++i) {
++    for (HashtableEntry* p = bucket(i); p != NULL; ) {
++      HashtableEntry* next = p->next();
++      oop string = p->literal();
++      // Use alternate hashing algorithm on the symbol in the first table
++      unsigned int hashValue = new_hash(string);
++      // Get a new index relative to the new table (can also change size)
++      int index = new_table->hash_to_index(hashValue);
++      p->set_hash(hashValue);
++      // Keep the shared bit in the Hashtable entry to indicate that this entry
++      // can't be deleted.   The shared bit is the LSB in the _next field so
++      // walking the hashtable past these entries requires
++      // BasicHashtableEntry::make_ptr() call.
++      bool keep_shared = p->is_shared();
++      unlink_entry(p);
++      new_table->add_entry(index, p);
++      if (keep_shared) {
++        p->set_shared();
++      }
++      p = next;
++    }
++  }
++  // give the new table the free list as well
++  new_table->copy_freelist(this);
++  assert(new_table->number_of_entries() == saved_entry_count, "lost entry on dictionary copy?");
++
++  // Destroy memory used by the buckets in the hashtable.  The memory
++  // for the elements has been used in a new table and is not
++  // destroyed.  The memory reuse will benefit resizing the SystemDictionary
++  // to avoid a memory allocation spike at safepoint.
++  free_buckets();
++}
++
++void BasicHashtable::free_buckets() {
++  if (NULL != _buckets) {
++    // Don't delete the buckets in the shared space.  They aren't
++    // allocated by os::malloc
++    if (!UseSharedSpaces ||
++        !FileMapInfo::current_info()->is_in_shared_space(_buckets)) {
++       FREE_C_HEAP_ARRAY(HashtableBucket, _buckets);
++    }
++    _buckets = NULL;
++  }
++}
++
++
+ // Reverse the order of elements in the hash buckets.
+ 
+ void BasicHashtable::reverse() {
+diff --git a/src/share/vm/utilities/hashtable.hpp b/src/share/vm/utilities/hashtable.hpp
+--- openjdk/hotspot/src/share/vm/utilities/hashtable.hpp
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.hpp
+@@ -177,6 +177,11 @@
+   void verify_lookup_length(double load);
+ #endif
+ 
++  enum {
++    rehash_count = 100,
++    rehash_multiple = 60
++  };
++
+   void initialize(int table_size, int entry_size, int number_of_entries);
+ 
+   // Accessor
+@@ -192,6 +197,29 @@
+   // Table entry management
+   BasicHashtableEntry* new_entry(unsigned int hashValue);
+ 
++  // Check that the table is unbalanced
++  bool check_rehash_table(int count);
++
++  // Used when moving the entry to another table
++  // Clean up links, but do not add to free_list
++  void unlink_entry(BasicHashtableEntry* entry) {
++    entry->set_next(NULL);
++    --_number_of_entries;
++  }
++
++  // Move over freelist and free block for allocation
++  void copy_freelist(BasicHashtable* src) {
++    _free_list = src->_free_list;
++    src->_free_list = NULL;
++    _first_free_entry = src->_first_free_entry;
++    src->_first_free_entry = NULL;
++    _end_block = src->_end_block;
++    src->_end_block = NULL;
++  }
++
++  // Free the buckets in this hashtable
++  void free_buckets();
++
+ public:
+   void set_entry(int index, BasicHashtableEntry* entry);
+ 
+@@ -210,11 +238,11 @@
+ 
+ public:
+   Hashtable(int table_size, int entry_size)
+-    : BasicHashtable(table_size, entry_size) { }
++    : BasicHashtable(table_size, entry_size), _seed(0)  { }
+ 
+   Hashtable(int table_size, int entry_size,
+                    HashtableBucket* buckets, int number_of_entries)
+-    : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
++    : BasicHashtable(table_size, entry_size, buckets, number_of_entries), _seed(0) { }
+ 
+   // Invoke "f->do_oop" on the locations of all oops in the table.
+   void oops_do(OopClosure* f);
+@@ -234,8 +262,6 @@
+ 
+ protected:
+ 
+-  static unsigned int hash_symbol(const char* s, int len);
+-
+   unsigned int compute_hash(symbolHandle name) {
+     return (unsigned int) name->identity_hash();
+   }
+@@ -256,6 +282,17 @@
+   HashtableEntry** bucket_addr(int i) {
+     return (HashtableEntry**)BasicHashtable::bucket_addr(i);
+   }
++
++  // Function to move these elements into the new table.
++  void move_to(Hashtable* new_table);
++  bool use_alternate_hashcode()  { return _seed != 0; }
++  jint seed()                    { return _seed; }
++  void set_seed(jint seed)       { _seed = seed; }
++
++ private:
++  jint _seed;
++
++  unsigned int new_hash(oop string);
+ };
+ 
+ 
+diff --git a/src/share/vm/utilities/hashtable.inline.hpp b/src/share/vm/utilities/hashtable.inline.hpp
+--- openjdk/hotspot/src/share/vm/utilities/hashtable.inline.hpp
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.inline.hpp
+@@ -30,27 +30,6 @@
+ 
+ // Inline function definitions for hashtable.hpp.
+ 
+-
+-// --------------------------------------------------------------------------
+-// Hash function
+-
+-// We originally used hashpjw, but hash P(31) gives just as good results
+-// and is slighly faster. We would like a hash function that looks at every
+-// character, since package names have large common prefixes, and also because
+-// hash_or_fail does error checking while iterating.
+-
+-// hash P(31) from Kernighan & Ritchie
+-
+-inline unsigned int Hashtable::hash_symbol(const char* s, int len) {
+-  unsigned int h = 0;
+-  while (len-- > 0) {
+-    h = 31*h + (unsigned) *s;
+-    s++;
+-  }
+-  return h;
+-}
+-
+-
+ // --------------------------------------------------------------------------
+ 
+ // Initialize a table.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/hs20/7158804.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,28 @@
+# HG changeset patch
+# User dbuck
+# Date 1342799006 25200
+# Node ID fde4cc8479824449b03abedd5357500aec92e990
+# Parent  f7493d50b47d3946902e18153bcd912e37589d00
+7158804: Improve config file parsing
+Summary: see bugdb 13784108 for details
+Reviewed-by: vikram, kamg
+
+diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
+--- openjdk/hotspot/src/share/vm/runtime/arguments.cpp
++++ openjdk/hotspot/src/share/vm/runtime/arguments.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 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
+@@ -842,7 +842,7 @@
+   bool result         = true;
+ 
+   int c = getc(stream);
+-  while(c != EOF) {
++  while(c != EOF && pos < (int)(sizeof(token)-1)) {
+     if (in_white_space) {
+       if (in_comment) {
+         if (c == '\n') in_comment = false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/original/7158800.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,1389 @@
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/altHashing.cpp openjdk/hotspot/src/share/vm/classfile/altHashing.cpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/altHashing.cpp	1970-01-01 01:00:00.000000000 +0100
++++ openjdk/hotspot/src/share/vm/classfile/altHashing.cpp	2012-10-11 22:16:15.578152329 +0100
+@@ -0,0 +1,300 @@
++/*
++ * 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.
++ *
++ */
++
++# include "incls/_precompiled.incl"
++# include "incls/_altHashing.cpp.incl"
++
++// Get the hash code of the classes mirror if it exists, otherwise just
++// return a random number, which is one of the possible hash code used for
++// objects.  We don't want to call the synchronizer hash code to install
++// this value because it may safepoint.
++intptr_t object_hash(klassOop k) {
++  intptr_t hc = Klass::cast(k)->java_mirror()->mark()->hash();
++  return hc != markOopDesc::no_hash ? hc : os::random();
++}
++
++// Seed value used for each alternative hash calculated.
++jint AltHashing::compute_seed() {
++  jlong nanos = os::javaTimeNanos();
++  jlong now = os::javaTimeMillis();
++  jint SEED_MATERIAL[8] = {
++            (jint) object_hash(SystemDictionary::String_klass()),
++            (jint) object_hash(SystemDictionary::System_klass()),
++            (jint) os::random(),  // current thread isn't a java thread
++            (jint) (((julong)nanos) >> 32),
++            (jint) nanos,
++            (jint) (((julong)now) >> 32),
++            (jint) now,
++            (jint) (os::javaTimeNanos() >> 2)
++  };
++
++  return murmur3_32(SEED_MATERIAL, 8);
++}
++
++
++// Murmur3 hashing for Symbol
++jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) {
++  jint h1 = seed;
++  int count = len;
++  int offset = 0;
++
++  // body
++  while (count >= 4) {
++    jint 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) {
++    jint 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 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Murmur3 hashing for Strings
++jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int count = len;
++
++  // body
++  while (count >= 2) {
++    jchar d1 = data[off++] & 0xFFFF;
++    jchar d2 = data[off++];
++    jint k1 = (d1 | d2 << 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 * 2; // (Character.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Hash used for the seed.
++jint AltHashing::murmur3_32(jint seed, const int* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int end = len;
++
++  // body
++  while (off < end) {
++    jint 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 * 4; // (Integer.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((juint)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((juint)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((juint)h1) >> 16;
++
++  return h1;
++}
++
++jint AltHashing::murmur3_32(const int* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++#ifndef PRODUCT
++// Overloaded versions for internal test.
++jint AltHashing::murmur3_32(const jbyte* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++jint AltHashing::murmur3_32(const jchar* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++// Internal test for alternate hashing.  Translated from JDK version
++// test/sun/misc/Hashing.java
++static const jbyte ONE_BYTE[] = { (jbyte) 0x80};
++static const jbyte TWO_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81};
++static const jchar ONE_CHAR[] = { (jchar) 0x8180};
++static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82};
++static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83};
++static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382};
++static const jint ONE_INT[] = { 0x83828180};
++static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85};
++static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584};
++static const jbyte EIGHT_BYTE[] = {
++  (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82,
++  (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85,
++  (jbyte) 0x86, (jbyte) 0x87};
++static const jchar FOUR_CHAR[] = {
++  (jchar) 0x8180, (jchar) 0x8382,
++  (jchar) 0x8584, (jchar) 0x8786};
++
++static const jint TWO_INT[] = { 0x83828180, 0x87868584};
++
++static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;
++
++void AltHashing::testMurmur3_32_ByteArray() {
++  // printf("testMurmur3_32_ByteArray\n");
++
++  jbyte* vector = new jbyte[256];
++  jbyte* hashes = new jbyte[4 * 256];
++
++  for (int i = 0; i < 256; i++) {
++    vector[i] = (jbyte) i;
++  }
++
++  // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
++  for (int i = 0; i < 256; i++) {
++    jint hash = murmur3_32(256 - i, vector, i);
++    hashes[i * 4] = (jbyte) hash;
++    hashes[i * 4 + 1] = (jbyte) (((juint)hash) >> 8);
++    hashes[i * 4 + 2] = (jbyte) (((juint)hash) >> 16);
++    hashes[i * 4 + 3] = (jbyte) (((juint)hash) >> 24);
++  }
++
++  // hash to get const result.
++  juint final_hash = murmur3_32(hashes, 4*256);
++
++  assert (MURMUR3_32_X86_CHECK_VALUE == final_hash,
++    err_msg(
++        "Calculated hash result not as expected. Expected %08X got %08X\n",
++        MURMUR3_32_X86_CHECK_VALUE,
++        final_hash));
++}
++
++void AltHashing::testEquivalentHashes() {
++  jint jbytes, jchars, ints;
++
++  // printf("testEquivalentHashes\n");
++
++  jbytes = murmur3_32(TWO_BYTE, 2);
++  jchars = murmur3_32(ONE_CHAR, 1);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(FOUR_BYTE, 4);
++  jchars = murmur3_32(TWO_CHAR, 2);
++  ints = murmur3_32(ONE_INT, 1);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++
++  jbytes = murmur3_32(SIX_BYTE, 6);
++  jchars = murmur3_32(THREE_CHAR, 3);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(EIGHT_BYTE, 8);
++  jchars = murmur3_32(FOUR_CHAR, 4);
++  ints = murmur3_32(TWO_INT, 2);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++}
++
++// Returns true if the alternate hashcode is correct
++void AltHashing::test_alt_hash() {
++  testMurmur3_32_ByteArray();
++  testEquivalentHashes();
++}
++#endif // PRODUCT
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/altHashing.hpp openjdk/hotspot/src/share/vm/classfile/altHashing.hpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/altHashing.hpp	1970-01-01 01:00:00.000000000 +0100
++++ openjdk/hotspot/src/share/vm/classfile/altHashing.hpp	2012-10-11 22:16:15.578152329 +0100
+@@ -0,0 +1,59 @@
++/*
++ * 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.
++ *
++ */
++
++#ifndef SHARE_VM_CLASSFILE_ALTHASHING_HPP
++#define SHARE_VM_CLASSFILE_ALTHASHING_HPP
++
++/**
++ * Hashing utilities.
++ *
++ * Implementation of Murmur3 hashing.
++ * This code was translated from src/share/classes/sun/misc/Hashing.java
++ * code in the JDK.
++ */
++
++class AltHashing : AllStatic {
++
++  // utility function copied from java/lang/Integer
++  static jint Integer_rotateLeft(jint i, int distance) {
++    return (i << distance) | (((juint)i) >> (32-distance));
++  }
++  static jint murmur3_32(const int* data, int len);
++  static jint murmur3_32(jint seed, const int* data, int len);
++
++#ifndef PRODUCT
++  // Hashing functions used for internal testing
++  static jint murmur3_32(const jbyte* data, int len);
++  static jint murmur3_32(const jchar* data, int len);
++  static void testMurmur3_32_ByteArray();
++  static void testEquivalentHashes();
++#endif // PRODUCT
++
++ public:
++  static jint compute_seed();
++  static jint murmur3_32(jint seed, const jbyte* data, int len);
++  static jint murmur3_32(jint seed, const jchar* data, int len);
++  NOT_PRODUCT(static void test_alt_hash();)
++};
++#endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/javaClasses.cpp openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/javaClasses.cpp	2011-02-28 16:03:17.000000000 +0000
++++ openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp	2012-10-11 22:16:15.578152329 +0100
+@@ -247,6 +247,28 @@
+   return result;
+ }
+ 
++unsigned int java_lang_String::to_hash(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string will hash to zero with String.toHash() function.
++  if (length == 0) return 0;
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return java_lang_String::to_hash(value->char_at_addr(offset), length);
++}
++
++unsigned int java_lang_String::hash_string(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string doesn't hash necessarily hash to zero.
++  if (length == 0) {
++    return StringTable::hash_string(NULL, 0);
++  }
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return StringTable::hash_string(value->char_at_addr(offset), length);
++}
++
+ symbolHandle java_lang_String::as_symbol(Handle java_string, TRAPS) {
+   oop          obj    = java_string();
+   typeArrayOop value  = java_lang_String::value(obj);
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/javaClasses.hpp openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/javaClasses.hpp	2011-02-28 16:03:17.000000000 +0000
++++ openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp	2012-10-11 22:16:15.578152329 +0100
+@@ -99,6 +99,30 @@
+   static char*  as_platform_dependent_str(Handle java_string, TRAPS);
+   static jchar* as_unicode_string(oop java_string, int& length);
+ 
++  // Compute the hash value for a java.lang.String object which would
++  // contain the characters passed in.
++  //
++  // As the hash value used by the String object itself, in
++  // String.hashCode().  This value is normally calculated in Java code
++  // in the String.hashCode method(), but is precomputed for String
++  // objects in the shared archive file.
++  // hash P(31) from Kernighan & Ritchie
++  //
++  // For this reason, THIS ALGORITHM MUST MATCH String.toHash().
++  template <typename T> static unsigned int to_hash(T* s, int len) {
++    unsigned int h = 0;
++    while (len-- > 0) {
++      h = 31*h + (unsigned int) *s;
++      s++;
++    }
++    return h;
++  }
++  static unsigned int to_hash(oop java_string);
++
++  // This is the string hash code used by the StringTable, which may be
++  // the same as String.toHash or an alternate hash code.
++  static unsigned int hash_string(oop java_string);
++
+   static bool equals(oop java_string, jchar* chars, int len);
+ 
+   // Conversion between '.' and '/' formats
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/symbolTable.cpp openjdk/hotspot/src/share/vm/classfile/symbolTable.cpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/symbolTable.cpp	2011-02-28 16:03:17.000000000 +0000
++++ openjdk/hotspot/src/share/vm/classfile/symbolTable.cpp	2012-10-11 22:19:55.389838184 +0100
+@@ -28,12 +28,35 @@
+ // --------------------------------------------------------------------------
+ 
+ SymbolTable* SymbolTable::_the_table = NULL;
++bool SymbolTable::_needs_rehashing = false;
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing strings.   Set flag to use the alternate hash code afterwards.
++void SymbolTable::rehash_table() {
++
++  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
++  // This should never happen with -Xshare:dump but it might in testing mode.
++  if (DumpSharedSpaces) return;
++  // Create a new symbol table
++  SymbolTable* new_table = new SymbolTable();
++
++  the_table()->move_to(new_table);
++
++  // Delete the table and buckets (entries are reused in new table).
++  delete _the_table;
++  // Don't check if we need rehashing until the table gets unbalanced again.
++  // Then rehash with a new global seed.
++  _needs_rehashing = false;
++  _the_table = new_table;
++}
+ 
+ // Lookup a symbol in a bucket.
+ 
+ symbolOop SymbolTable::lookup(int index, const char* name,
+                               int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
++    count++;
+     if (e->hash() == hash) {
+       symbolOop sym = symbolOop(e->literal());
+       if (sym->equals(name, len)) {
+@@ -41,9 +64,20 @@
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
++// Pick hashing algorithm.
++unsigned int SymbolTable::hash_symbol(const char* s, int len) {
++  return the_table()->use_alternate_hashcode() ?
++           AltHashing::murmur3_32(the_table()->seed(), (const jbyte*)s, len) :
++           java_lang_String::to_hash(s, len);
++}
++
+ 
+ // We take care not to be blocking while holding the
+ // SymbolTable_lock. Otherwise, the system might deadlock, since the
+@@ -61,8 +95,17 @@
+   // Found
+   if (s != NULL) return s;
+ 
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)name, len, CHECK_NULL);
++  symbolHandle sym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
+   // Otherwise, add to symbol to table
+-  return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL);
++  return the_table()->basic_add(sym, index, (u1*)name, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) {
+@@ -98,7 +141,16 @@
+   // We can't include the code in No_Safepoint_Verifier because of the
+   // ResourceMark.
+ 
+-  return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL);
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)buffer, len, CHECK_NULL);
++  symbolHandle newsym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
++  return the_table()->basic_add(newsym, index, (u1*)buffer, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup_only(const char* name, int len,
+@@ -146,36 +198,68 @@
+ void SymbolTable::add(constantPoolHandle cp, int names_count,
+                       const char** names, int* lengths, int* cp_indices,
+                       unsigned int* hashValues, TRAPS) {
+-  SymbolTable* table = the_table();
+-  bool added = table->basic_add(cp, names_count, names, lengths,
+-                                cp_indices, hashValues, CHECK);
+-  if (!added) {
++
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop sym_oops[symbol_alloc_batch_size];
++  bool allocated = sk->allocate_symbols(names_count, names, lengths,
++                                        sym_oops, CHECK);
++  if (!allocated) {
+     // do it the hard way
+     for (int i=0; i<names_count; i++) {
++      assert(!Universe::heap()->is_in_reserved(names[i]) || GC_locker::is_active(),
++         "proposed name of symbol must be stable");
++
++      // We assume that lookup() has been called already, that it failed,
++      // and symbol was not found.  We create the symbol here.
++      symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++      symbolOop s_oop = sk->allocate_symbol((u1*)names[i], lengths[i], CHECK);
++      symbolHandle sym (THREAD, s_oop);
++
++      // Allocation must be done before grabbing the SymbolTable_lock lock
++      MutexLocker ml(SymbolTable_lock, THREAD);
++
++      SymbolTable* table = the_table();
+       int index = table->hash_to_index(hashValues[i]);
+-      symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i],
++      symbolOop s = table->basic_add(sym, index, (u1*)names[i], lengths[i],
+                                        hashValues[i], CHECK);
+-      cp->symbol_at_put(cp_indices[i], sym);
++      cp->symbol_at_put(cp_indices[i], s);
+     }
++    return;
+   }
+-}
+-
+-symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
+-                                 unsigned int hashValue, TRAPS) {
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
+ 
+-  // We assume that lookup() has been called already, that it failed,
+-  // and symbol was not found.  We create the symbol here.
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL);
+-  symbolHandle sym (THREAD, s_oop);
++  symbolHandle syms[symbol_alloc_batch_size];
++  for (int i=0; i<names_count; i++) {
++    syms[i] = symbolHandle(THREAD, sym_oops[i]);
++  }
+ 
+-  // Allocation must be done before grapping the SymbolTable_lock lock
++  // Allocation must be done before grabbing the SymbolTable_lock lock
+   MutexLocker ml(SymbolTable_lock, THREAD);
+ 
++  SymbolTable* table = the_table();
++  bool added = table->basic_add(syms, cp, names_count, names, lengths,
++                                cp_indices, hashValues, CHECK);
++  assert(added, "should always return true");
++}
++
++symbolOop SymbolTable::basic_add(symbolHandle sym, int index_arg, u1 *name, int len,
++                                 unsigned int hashValue_arg, TRAPS) {
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
++
+   assert(sym->equals((char*)name, len), "symbol must be properly initialized");
+ 
++  // Check if the symbol table has been rehashed, if so, need to recalculate
++  // the hash value and index.
++  unsigned int hashValue;
++  int index;
++  if (use_alternate_hashcode()) {
++    hashValue = hash_symbol((const char*)name, len);
++    index = hash_to_index(hashValue);
++  } else {
++    hashValue = hashValue_arg;
++    index = index_arg;
++  }
++
+   // Since look-up was done lock-free, we need to check if another
+   // thread beat us in the race to insert the symbol.
+ 
+@@ -191,48 +275,42 @@
+   return sym();
+ }
+ 
+-bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
++bool SymbolTable::basic_add(symbolHandle* syms,
++                            constantPoolHandle cp, int names_count,
+                             const char** names, int* lengths,
+                             int* cp_indices, unsigned int* hashValues,
+                             TRAPS) {
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop sym_oops[symbol_alloc_batch_size];
+-  bool allocated = sk->allocate_symbols(names_count, names, lengths,
+-                                        sym_oops, CHECK_false);
+-  if (!allocated) {
+-    return false;
+-  }
+-  symbolHandle syms[symbol_alloc_batch_size];
+-  int i;
+-  for (i=0; i<names_count; i++) {
+-    syms[i] = symbolHandle(THREAD, sym_oops[i]);
+-  }
+-
+-  // Allocation must be done before grabbing the SymbolTable_lock lock
+-  MutexLocker ml(SymbolTable_lock, THREAD);
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+-  for (i=0; i<names_count; i++) {
++  for (int i=0; i<names_count; i++) {
+     assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
++    // Check if the symbol table has been rehashed, if so, need to recalculate
++    // the hash value.
++    unsigned int hashValue;
++    if (use_alternate_hashcode()) {
++      hashValue = hash_symbol(names[i], lengths[i]);
++    } else {
++      hashValue = hashValues[i];
++    }
+     // Since look-up was done lock-free, we need to check if another
+     // thread beat us in the race to insert the symbol.
+-    int index = hash_to_index(hashValues[i]);
+-    symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]);
++    int index = hash_to_index(hashValue);
++    symbolOop test = lookup(index, names[i], lengths[i], hashValue);
+     if (test != NULL) {
+       // A race occurred and another thread introduced the symbol, this one
+       // will be dropped and collected. Use test instead.
+       cp->symbol_at_put(cp_indices[i], test);
+     } else {
+       symbolOop sym = syms[i]();
+-      HashtableEntry* entry = new_entry(hashValues[i], sym);
++      HashtableEntry* entry = new_entry(hashValue, sym);
+       add_entry(index, entry);
+       cp->symbol_at_put(cp_indices[i], sym);
+     }
+   }
+-
+-  return true;
++  return true;  // always returns true
+ }
+ 
+-
+ void SymbolTable::verify() {
+   for (int i = 0; i < the_table()->table_size(); ++i) {
+     HashtableEntry* p = the_table()->bucket(i);
+@@ -241,7 +319,7 @@
+       guarantee(s != NULL, "symbol is NULL");
+       s->verify();
+       guarantee(s->is_perm(), "symbol not in permspace");
+-      unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
++      unsigned int h = hash_symbol((const char*)s->bytes(), s->utf8_length());
+       guarantee(p->hash() == h, "broken hash in symbol table entry");
+       guarantee(the_table()->hash_to_index(h) == i,
+                 "wrong index in symbol table");
+@@ -249,6 +327,23 @@
+   }
+ }
+ 
++void SymbolTable::dump(outputStream* st) {
++  NumberSeq summary;
++  for (int i = 0; i < the_table()->table_size(); ++i) {
++    int count = 0;
++    for (HashtableEntry* e = the_table()->bucket(i);
++       e != NULL; e = e->next()) {
++      count++;
++    }
++    summary.add((double)count);
++  }
++  st->print_cr("SymbolTable statistics:");
++  st->print_cr("Number of buckets       : %7d", summary.num());
++  st->print_cr("Average bucket size     : %7.0f", summary.avg());
++  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
++  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
++  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
++}
+ 
+ //---------------------------------------------------------------------------
+ // Non-product code
+@@ -311,7 +406,6 @@
+   tty->print_cr(" %s %d: %d\n", "Number chains longer than",
+                     results_length, out_of_range);
+ }
+-
+ #endif // PRODUCT
+ 
+ // --------------------------------------------------------------------------
+@@ -357,66 +451,56 @@
+ // --------------------------------------------------------------------------
+ 
+ 
+-// Compute the hash value for a java.lang.String object which would
+-// contain the characters passed in. This hash value is used for at
+-// least two purposes.
+-//
+-// (a) As the hash value used by the StringTable for bucket selection
+-//     and comparison (stored in the HashtableEntry structures).  This
+-//     is used in the String.intern() method.
+-//
+-// (b) As the hash value used by the String object itself, in
+-//     String.hashCode().  This value is normally calculate in Java code
+-//     in the String.hashCode method(), but is precomputed for String
+-//     objects in the shared archive file.
+-//
+-//     For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
+-
+-int StringTable::hash_string(jchar* s, int len) {
+-  unsigned h = 0;
+-  while (len-- > 0) {
+-    h = 31*h + (unsigned) *s;
+-    s++;
+-  }
+-  return h;
+-}
++StringTable* StringTable::_the_table = NULL;
+ 
++bool StringTable::_needs_rehashing = false;
+ 
+-StringTable* StringTable::_the_table = NULL;
++// Pick hashing algorithm
++unsigned int StringTable::hash_string(const jchar* s, int len) {
++  return the_table()->use_alternate_hashcode() ? AltHashing::murmur3_32(the_table()->seed(), s, len) :
++                                    java_lang_String::to_hash(s, len);
++}
+ 
+ oop StringTable::lookup(int index, jchar* name,
+                         int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) {
++    count++;
+     if (l->hash() == hash) {
+       if (java_lang_String::equals(l->literal(), name, len)) {
+         return l->literal();
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
+ 
+-oop StringTable::basic_add(int index, Handle string_or_null, jchar* name,
+-                           int len, unsigned int hashValue, TRAPS) {
+-  debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
++oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
++                           int len, unsigned int hashValue_arg, TRAPS) {
+ 
+-  Handle string;
+-  // try to reuse the string if possible
+-  if (!string_or_null.is_null() && string_or_null()->is_perm()) {
+-    string = string_or_null;
+-  } else {
+-    string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
+-  }
+-
+-  // Allocation must be done before grapping the SymbolTable_lock lock
+-  MutexLocker ml(StringTable_lock, THREAD);
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+   assert(java_lang_String::equals(string(), name, len),
+          "string must be properly initialized");
+ 
++  // Check if the symbol table has been rehashed, if so, need to recalculate
++  // the hash value and index before second lookup.
++  unsigned int hashValue;
++  int index;
++  if (use_alternate_hashcode()) {
++    hashValue = hash_string(name, len);
++    index = hash_to_index(hashValue);
++  } else {
++    hashValue = hashValue_arg;
++    index = index_arg;
++  }
++
+   // Since look-up was done lock-free, we need to check if another
+   // thread beat us in the race to insert the symbol.
+ 
+@@ -446,13 +530,28 @@
+                         int len, TRAPS) {
+   unsigned int hashValue = hash_string(name, len);
+   int index = the_table()->hash_to_index(hashValue);
+-  oop string = the_table()->lookup(index, name, len, hashValue);
++  oop found_string = the_table()->lookup(index, name, len, hashValue);
+ 
+   // Found
+-  if (string != NULL) return string;
++  if (found_string != NULL) return found_string;
++
++  debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
++  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
++         "proposed name of symbol must be stable");
++
++  Handle string;
++  // try to reuse the string if possible
++  if (!string_or_null.is_null() && string_or_null()->is_perm()) {
++    string = string_or_null;
++  } else {
++    string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
++  }
++
++  // Allocation must be done before grabbing the StringTable_lock lock
++  MutexLocker ml(StringTable_lock, THREAD);
+ 
+   // Otherwise, add to symbol to table
+-  return the_table()->basic_add(index, string_or_null, name, len,
++  return the_table()->basic_add(index, string, name, len,
+                                 hashValue, CHECK_NULL);
+ }
+ 
+@@ -507,3 +606,41 @@
+     }
+   }
+ }
++
++void StringTable::dump(outputStream* st) {
++  NumberSeq summary;
++  for (int i = 0; i < the_table()->table_size(); ++i) {
++    HashtableEntry* p = the_table()->bucket(i);
++    int count = 0;
++    for ( ; p != NULL; p = p->next()) {
++      count++;
++    }
++    summary.add((double)count);
++  }
++  st->print_cr("StringTable statistics:");
++  st->print_cr("Number of buckets       : %7d", summary.num());
++  st->print_cr("Average bucket size     : %7.0f", summary.avg());
++  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
++  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
++  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
++}
++
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing strings.   Set flag to use the alternate hash code afterwards.
++void StringTable::rehash_table() {
++  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
++  // This should never happen with -Xshare:dump but it might in testing mode.
++  if (DumpSharedSpaces) return;
++  StringTable* new_table = new StringTable();
++
++  // Rehash the table
++  the_table()->move_to(new_table);
++
++  // Delete the table and buckets (entries are reused in new table).
++  delete _the_table;
++  // Don't check if we need rehashing until the table gets unbalanced again.
++  // Then rehash with a new global seed.
++  _needs_rehashing = false;
++  _the_table = new_table;
++}
+diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/symbolTable.hpp openjdk/hotspot/src/share/vm/classfile/symbolTable.hpp
+--- openjdk.orig/hotspot/src/share/vm/classfile/symbolTable.hpp	2011-02-28 16:03:17.000000000 +0000
++++ openjdk/hotspot/src/share/vm/classfile/symbolTable.hpp	2012-10-11 22:17:53.499788279 +0100
+@@ -33,6 +33,7 @@
+ //  - symbolTableEntrys are allocated in blocks to reduce the space overhead.
+ 
+ class BoolObjectClosure;
++class outputStream;
+ 
+ 
+ class SymbolTable : public Hashtable {
+@@ -42,10 +43,13 @@
+   // The symbol table
+   static SymbolTable* _the_table;
+ 
++  // Set if one bucket is out of balance due to hash algorithm deficiency
++  static bool _needs_rehashing;
++
+   // Adding elements
+-  symbolOop basic_add(int index, u1* name, int len,
++  symbolOop basic_add(symbolHandle sym, int index, u1* name, int len,
+                       unsigned int hashValue, TRAPS);
+-  bool basic_add(constantPoolHandle cp, int names_count,
++  bool basic_add(symbolHandle* syms, constantPoolHandle cp, int names_count,
+                  const char** names, int* lengths, int* cp_indices,
+                  unsigned int* hashValues, TRAPS);
+ 
+@@ -54,6 +58,8 @@
+     symbol_table_size = 20011
+   };
+ 
++  static unsigned int hash_symbol(const char* s, int len);
++
+   symbolOop lookup(int index, const char* name, int len, unsigned int hash);
+ 
+   SymbolTable()
+@@ -63,7 +69,6 @@
+     : Hashtable(symbol_table_size, sizeof (HashtableEntry), t,
+                 number_of_entries) {}
+ 
+-
+ public:
+   enum {
+     symbol_alloc_batch_size = 8
+@@ -130,6 +135,7 @@
+ 
+   // Debugging
+   static void verify();
++  static void dump(outputStream* st);
+ 
+   // Sharing
+   static void copy_buckets(char** top, char*end) {
+@@ -141,6 +147,10 @@
+   static void reverse(void* boundary = NULL) {
+     ((Hashtable*)the_table())->reverse(boundary);
+   }
++
++  // Rehash the symbol table if it gets out of balance
++  static void rehash_table();
++  static bool needs_rehashing()         { return _needs_rehashing; }
+ };
+ 
+ 
+@@ -151,8 +161,11 @@
+   // The string table
+   static StringTable* _the_table;
+ 
++  // Set if one bucket is out of balance due to hash algorithm deficiency
++  static bool _needs_rehashing;
++
+   static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
+-  oop basic_add(int index, Handle string_or_null, jchar* name, int len,
++  oop basic_add(int index, Handle string, jchar* name, int len,
+                 unsigned int hashValue, TRAPS);
+ 
+   // Table size
+@@ -185,10 +198,6 @@
+     _the_table = new StringTable(t, number_of_entries);
+   }
+ 
+-
+-  static int hash_string(jchar* s, int len);
+-
+-
+   // GC support
+   //   Delete pointers to otherwise-unreachable objects.
+   static void unlink(BoolObjectClosure* cl) {
+@@ -200,6 +209,14 @@
+     the_table()->Hashtable::oops_do(f);
+   }
+ 
++  // Hashing algorithm, used as the hash value used by the
++  //     StringTable for bucket selection and comparison (stored in the
++  //     HashtableEntry structures).  This is used in the String.intern() method.
++  static unsigned int hash_string(const jchar* s, int len);
++
++  // Internal test.
++  static void test_alt_hash() PRODUCT_RETURN;
++
+   // Probing
+   static oop lookup(symbolOop symbol);
+ 
+@@ -210,6 +227,7 @@
+ 
+   // Debugging
+   static void verify();
++  static void dump(outputStream* st);
+ 
+   // Sharing
+   static void copy_buckets(char** top, char*end) {
+@@ -221,4 +239,8 @@
+   static void reverse() {
+     ((BasicHashtable*)the_table())->reverse();
+   }
++
++  // Rehash the symbol table if it gets out of balance
++  static void rehash_table();
++  static bool needs_rehashing() { return _needs_rehashing; }
+ };
+diff -Nru openjdk.orig/hotspot/src/share/vm/memory/dump.cpp openjdk/hotspot/src/share/vm/memory/dump.cpp
+--- openjdk.orig/hotspot/src/share/vm/memory/dump.cpp	2011-02-28 16:03:19.000000000 +0000
++++ openjdk/hotspot/src/share/vm/memory/dump.cpp	2012-10-11 22:16:15.578152329 +0100
+@@ -47,8 +47,8 @@
+ // written later, increasing the likelihood that the shared page contain
+ // the hash can be shared.
+ //
+-// NOTE THAT the algorithm in StringTable::hash_string() MUST MATCH the
+-// algorithm in java.lang.String.hashCode().
++// NOTE THAT we have to call java_lang_String::to_hash() to match the
++// algorithm in java.lang.String.toHash().
+ 
+ class StringHashCodeClosure: public OopClosure {
+ private:
+@@ -73,7 +73,7 @@
+         } else {
+           int offset = java_lang_String::offset(obj);
+           jchar* s = value->char_at_addr(offset);
+-          hash = StringTable::hash_string(s, length);
++          hash = java_lang_String::to_hash(s, length);
+         }
+         obj->int_field_put(hash_offset, hash);
+       }
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/globals.hpp openjdk/hotspot/src/share/vm/runtime/globals.hpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/globals.hpp	2011-02-28 16:03:21.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/globals.hpp	2012-10-11 22:16:15.582152395 +0100
+@@ -2434,6 +2434,9 @@
+   product(bool, UseHeavyMonitors, false,                                    \
+           "use heavyweight instead of lightweight Java monitors")           \
+                                                                             \
++  product(bool, PrintStringTableStatistics, false,                          \
++          "print statistics about the StringTable and SymbolTable")         \
++                                                                            \
+   notproduct(bool, PrintSymbolTableSizeHistogram, false,                    \
+           "print histogram of the symbol table")                            \
+                                                                             \
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/init.cpp openjdk/hotspot/src/share/vm/runtime/init.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/init.cpp	2011-02-28 16:03:21.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/init.cpp	2012-10-11 22:16:15.582152395 +0100
+@@ -147,6 +147,10 @@
+       // Print the collected safepoint statistics.
+       SafepointSynchronize::print_stat_on_exit();
+     }
++    if (PrintStringTableStatistics) {
++      SymbolTable::dump(tty);
++      StringTable::dump(tty);
++    }
+     ostream_exit();
+   }
+ }
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/safepoint.cpp openjdk/hotspot/src/share/vm/runtime/safepoint.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/safepoint.cpp	2011-02-28 16:03:21.000000000 +0000
++++ openjdk/hotspot/src/share/vm/runtime/safepoint.cpp	2012-10-11 22:19:03.000955311 +0100
+@@ -471,8 +471,20 @@
+     CounterDecay::decay();
+   }
+ 
+-  TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime);
+-  NMethodSweeper::scan_stacks();
++  {
++    TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime);
++    NMethodSweeper::scan_stacks();
++  }
++
++  if (SymbolTable::needs_rehashing()) {
++    TraceTime t5("rehashing symbol table", TraceSafepointCleanupTime);
++    SymbolTable::rehash_table();
++  }
++
++  if (StringTable::needs_rehashing()) {
++    TraceTime t6("rehashing string table", TraceSafepointCleanupTime);
++    StringTable::rehash_table();
++  }
+ }
+ 
+ 
+diff -Nru openjdk.orig/hotspot/src/share/vm/utilities/hashtable.cpp openjdk/hotspot/src/share/vm/utilities/hashtable.cpp
+--- openjdk.orig/hotspot/src/share/vm/utilities/hashtable.cpp	2011-02-28 16:03:22.000000000 +0000
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.cpp	2012-10-11 22:20:11.326107281 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 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
+@@ -63,7 +63,6 @@
+ 
+ HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) {
+   HashtableEntry* entry;
+-
+   entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue);
+   entry->set_literal(obj);   // clears literal string field
+   HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
+@@ -79,18 +78,24 @@
+   // entries at a safepoint.
+   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+   for (int i = 0; i < table_size(); ++i) {
+-    for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) {
+-      HashtableEntry* entry = *p;
+-      if (entry->is_shared()) {
++    HashtableEntry** p = bucket_addr(i);
++    HashtableEntry* entry = bucket(i);
++    while (entry != NULL) {
++      // Shared entries are normally at the end of the bucket and if we run into
++      // a shared entry, then there is nothing more to remove. However, if we
++      // have rehashed the table, then the shared entries are no longer at the
++      // end of the bucket.
++      if (entry->is_shared() && !use_alternate_hashcode()) {
+         break;
+       }
+       assert(entry->literal() != NULL, "just checking");
+-      if (is_alive->do_object_b(entry->literal())) {
++      if (entry->is_shared() || is_alive->do_object_b(entry->literal())) {
+         p = entry->next_addr();
+       } else {
+         *p = entry->next();
+         free_entry(entry);
+       }
++      entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
+     }
+   }
+ }
+@@ -116,6 +121,96 @@
+   }
+ }
+ 
++
++// Check to see if the hashtable is unbalanced.  The caller set a flag to
++// rehash at the next safepoint.  If this bucket is 60 times greater than the
++// expected average bucket length, it's an unbalanced hashtable.
++// This is somewhat an arbitrary heuristic but if one bucket gets to
++// rehash_count which is currently 100, there's probably something wrong.
++
++bool BasicHashtable::check_rehash_table(int count) {
++  assert(table_size() != 0, "underflow");
++  if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
++    // Set a flag for the next safepoint, which should be at some guaranteed
++    // safepoint interval.
++    return true;
++  }
++  return false;
++}
++
++unsigned int Hashtable::new_hash(oop string) {
++  ResourceMark rm;
++  int length;
++  if (java_lang_String::is_instance(string)) {
++    jchar* chars = java_lang_String::as_unicode_string(string, length);
++    // Use alternate hashing algorithm on the string
++    return AltHashing::murmur3_32(seed(), chars, length);
++  } else {
++    // Use alternate hashing algorithm on this symbol.
++    symbolOop symOop = (symbolOop) string;
++    return AltHashing::murmur3_32(seed(), (const jbyte*)symOop->bytes(), symOop->utf8_length());
++  }
++}
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing elements.   This can be used to change the hash code
++// and could in the future change the size of the table.
++
++void Hashtable::move_to(Hashtable* new_table) {
++  // Initialize the global seed for hashing.
++  assert(new_table->seed() == 0, "should be zero");
++  _seed = AltHashing::compute_seed();
++  assert(seed() != 0, "shouldn't be zero");
++  new_table->set_seed(_seed);
++
++  int saved_entry_count = this->number_of_entries();
++  
++  // Iterate through the table and create a new entry for the new table
++  for (int i = 0; i < new_table->table_size(); ++i) {
++    for (HashtableEntry* p = bucket(i); p != NULL; ) {
++      HashtableEntry* next = p->next();
++      oop string = p->literal();
++      // Use alternate hashing algorithm on the symbol in the first table
++      unsigned int hashValue = new_hash(string);
++      // Get a new index relative to the new table (can also change size)
++      int index = new_table->hash_to_index(hashValue);
++      p->set_hash(hashValue);
++      // Keep the shared bit in the Hashtable entry to indicate that this entry
++      // can't be deleted.   The shared bit is the LSB in the _next field so
++      // walking the hashtable past these entries requires
++      // BasicHashtableEntry::make_ptr() call.
++      bool keep_shared = p->is_shared();
++      unlink_entry(p);
++      new_table->add_entry(index, p);
++      if (keep_shared) {
++        p->set_shared();
++      }
++      p = next;
++    }
++  }
++  // give the new table the free list as well
++  new_table->copy_freelist(this);
++  assert(new_table->number_of_entries() == saved_entry_count, "lost entry on dictionary copy?");
++
++  // Destroy memory used by the buckets in the hashtable.  The memory
++  // for the elements has been used in a new table and is not
++  // destroyed.  The memory reuse will benefit resizing the SystemDictionary
++  // to avoid a memory allocation spike at safepoint.
++  free_buckets();
++}
++
++void BasicHashtable::free_buckets() {
++  if (NULL != _buckets) {
++    // Don't delete the buckets in the shared space.  They aren't
++    // allocated by os::malloc
++    if (!UseSharedSpaces ||
++        !FileMapInfo::current_info()->is_in_shared_space(_buckets)) {
++       FREE_C_HEAP_ARRAY(HashtableBucket, _buckets);
++    }
++    _buckets = NULL;
++  }
++}
++
+ 
+ // Reverse the order of elements in the hash buckets.
+ 
+diff -Nru openjdk.orig/hotspot/src/share/vm/utilities/hashtable.hpp openjdk/hotspot/src/share/vm/utilities/hashtable.hpp
+--- openjdk.orig/hotspot/src/share/vm/utilities/hashtable.hpp	2011-02-28 16:03:22.000000000 +0000
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.hpp	2012-10-11 22:16:15.582152395 +0100
+@@ -169,6 +169,11 @@
+   void verify_lookup_length(double load);
+ #endif
+ 
++  enum {
++    rehash_count = 100,
++    rehash_multiple = 60
++  };
++
+   void initialize(int table_size, int entry_size, int number_of_entries);
+ 
+   // Accessor
+@@ -184,6 +189,29 @@
+   // Table entry management
+   BasicHashtableEntry* new_entry(unsigned int hashValue);
+ 
++  // Check that the table is unbalanced
++  bool check_rehash_table(int count);
++
++  // Used when moving the entry to another table
++  // Clean up links, but do not add to free_list
++  void unlink_entry(BasicHashtableEntry* entry) {
++    entry->set_next(NULL);
++    --_number_of_entries;
++  }
++
++  // Move over freelist and free block for allocation
++  void copy_freelist(BasicHashtable* src) {
++    _free_list = src->_free_list;
++    src->_free_list = NULL;
++    _first_free_entry = src->_first_free_entry;
++    src->_first_free_entry = NULL;
++    _end_block = src->_end_block;
++    src->_end_block = NULL;
++  }
++
++  // Free the buckets in this hashtable
++  void free_buckets();
++
+ public:
+   void set_entry(int index, BasicHashtableEntry* entry);
+ 
+@@ -202,11 +230,11 @@
+ 
+ public:
+   Hashtable(int table_size, int entry_size)
+-    : BasicHashtable(table_size, entry_size) { }
++    : BasicHashtable(table_size, entry_size), _seed(0)  { }
+ 
+   Hashtable(int table_size, int entry_size,
+                    HashtableBucket* buckets, int number_of_entries)
+-    : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
++    : BasicHashtable(table_size, entry_size, buckets, number_of_entries), _seed(0) { }
+ 
+   // Invoke "f->do_oop" on the locations of all oops in the table.
+   void oops_do(OopClosure* f);
+@@ -226,8 +254,6 @@
+ 
+ protected:
+ 
+-  static unsigned int hash_symbol(const char* s, int len);
+-
+   unsigned int compute_hash(symbolHandle name) {
+     return (unsigned int) name->identity_hash();
+   }
+@@ -248,6 +274,17 @@
+   HashtableEntry** bucket_addr(int i) {
+     return (HashtableEntry**)BasicHashtable::bucket_addr(i);
+   }
++
++  // Function to move these elements into the new table.
++  void move_to(Hashtable* new_table);
++  bool use_alternate_hashcode()  { return _seed != 0; }
++  jint seed()                    { return _seed; }
++  void set_seed(jint seed)       { _seed = seed; }
++
++ private:
++  jint _seed;
++
++  unsigned int new_hash(oop string);
+ };
+ 
+ 
+diff -Nru openjdk.orig/hotspot/src/share/vm/utilities/hashtable.inline.hpp openjdk/hotspot/src/share/vm/utilities/hashtable.inline.hpp
+--- openjdk.orig/hotspot/src/share/vm/utilities/hashtable.inline.hpp	2011-02-28 16:03:22.000000000 +0000
++++ openjdk/hotspot/src/share/vm/utilities/hashtable.inline.hpp	2012-10-11 22:16:15.582152395 +0100
+@@ -24,27 +24,6 @@
+ 
+ // Inline function definitions for hashtable.hpp.
+ 
+-
+-// --------------------------------------------------------------------------
+-// Hash function
+-
+-// We originally used hashpjw, but hash P(31) gives just as good results
+-// and is slighly faster. We would like a hash function that looks at every
+-// character, since package names have large common prefixes, and also because
+-// hash_or_fail does error checking while iterating.
+-
+-// hash P(31) from Kernighan & Ritchie
+-
+-inline unsigned int Hashtable::hash_symbol(const char* s, int len) {
+-  unsigned int h = 0;
+-  while (len-- > 0) {
+-    h = 31*h + (unsigned) *s;
+-    s++;
+-  }
+-  return h;
+-}
+-
+-
+ // --------------------------------------------------------------------------
+ 
+ // Initialize a table.
+--- openjdk.orig/hotspot/src/share/vm/includeDB_core	2011-02-28 16:03:19.000000000 +0000
++++ openjdk/hotspot/src/share/vm/includeDB_core	2012-10-11 22:46:50.055983261 +0100
+@@ -148,5 +148,13 @@
+ 
+ allocation.inline.hpp                   os.hpp
+ 
++altHashing.cpp				altHashing.hpp
++altHashing.cpp				markOop.hpp
++altHashing.cpp				thread.hpp
++altHashing.cpp				symbolTable.hpp
++altHashing.cpp				systemDictionary.hpp
++
++altHashing.hpp				jni.h
++ 
+ aprofiler.cpp                           aprofiler.hpp
+ aprofiler.cpp                           collectedHeap.inline.hpp
+@@ -1906,12 +1911,14 @@
+ handles.inline.hpp                      thread_<os_family>.inline.hpp
+ 
+ hashtable.cpp                           allocation.inline.hpp
++hashtable.cpp				altHashing.hpp
+ hashtable.cpp                           dtrace.hpp
++hashtable.cpp				filemap.hpp
+ hashtable.cpp                           hashtable.hpp
+ hashtable.cpp                           hashtable.inline.hpp
+ hashtable.cpp                           oop.inline.hpp
+ hashtable.cpp                           resourceArea.hpp
+ hashtable.cpp                           safepoint.hpp
+ 
+ hashtable.hpp                           allocation.hpp
+ hashtable.hpp                           handles.hpp
+@@ -4013,6 +4019,7 @@
+ symbolOop.hpp                           typeArrayOop.hpp
+ symbolOop.hpp                           utf8.hpp
+ 
++symbolTable.cpp				altHashing.hpp
+ symbolTable.cpp                         collectedHeap.inline.hpp
+ symbolTable.cpp                         filemap.hpp
+ symbolTable.cpp                         gcLocker.inline.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20121016/original/7158804.patch	Fri Oct 12 02:18:24 2012 +0100
@@ -0,0 +1,19 @@
+diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp openjdk/hotspot/src/share/vm/runtime/arguments.cpp
+--- openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp	2012-10-11 22:21:58.027915386 +0100
++++ openjdk/hotspot/src/share/vm/runtime/arguments.cpp	2012-10-11 22:25:01.851055628 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 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
+@@ -786,7 +786,7 @@
+   bool result         = true;
+ 
+   int c = getc(stream);
+-  while(c != EOF) {
++  while(c != EOF && pos < (int)(sizeof(token)-1)) {
+     if (in_white_space) {
+       if (in_comment) {
+         if (c == '\n') in_comment = false;
--- a/patches/ssl.patch	Wed Sep 05 11:43:29 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
---- ../openjdkb23/openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java	2007-10-30 04:38:10.000000000 -0400
-+++ openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java	2007-11-13 13:06:01.000000000 -0500
-@@ -36,6 +36,7 @@
- import java.security.PrivilegedExceptionAction;
- import java.security.PrivilegedActionException;
- import java.security.cert.X509Certificate;
-+import java.security.spec.AlgorithmParameterSpec;
- 
- import javax.crypto.*;
- import javax.crypto.spec.*;
-@@ -688,8 +683,8 @@
-         SecretKey masterSecret;
-         try {
-             KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsMasterSecret");
--            kg.init(spec);
--            masterSecret = kg.generateKey();
-+            kg.init((AlgorithmParameterSpec) spec);
-+	    masterSecret = kg.generateKey();
-         } catch (GeneralSecurityException e) {
-             // For RSA premaster secrets, do not signal a protocol error
-             // due to the Bleichenbacher attack. See comments further down.
---- ../openjdkb23/openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	2007-10-30 04:38:10.000000000 -0400
-+++ openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java	2007-11-13 13:06:42.000000000 -0500
-@@ -36,6 +36,8 @@
- import javax.net.ssl.*;
- 
- import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
-+import java.security.spec.AlgorithmParameterSpec;
-+
- 
- /**
-  * This is the client key exchange message (CLIENT --> SERVER) used with
-@@ -104,8 +106,8 @@
- 
-         try {
-             KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
--            kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor));
--            preMaster = kg.generateKey();
-+            kg.init((AlgorithmParameterSpec) (new TlsRsaPremasterSecretParameterSpec(major, minor)));
-+	    preMaster = kg.generateKey();
- 
-             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
-             cipher.init(Cipher.WRAP_MODE, publicKey, generator);