changeset 6506:cdc7f9be3707

Merge
author lana
date Tue, 23 Oct 2012 09:41:52 -0700
parents 37a6ead4a357 29b58cb8e4fc
children e6fbbb2c610d
files src/share/classes/sun/security/tools/CertAndKeyGen.java src/share/classes/sun/security/tools/JarSigner.java src/share/classes/sun/security/tools/JarSignerResources.java src/share/classes/sun/security/tools/JarSignerResources_ja.java src/share/classes/sun/security/tools/JarSignerResources_zh_CN.java src/share/classes/sun/security/tools/KeyTool.java src/share/classes/sun/security/tools/TimestampedSigner.java src/windows/classes/java/io/Win32FileSystem.java src/windows/native/java/io/Win32FileSystem_md.c test/com/sun/jndi/ldap/LdapsReadTimeoutTest.java test/com/sun/jndi/ldap/ReadTimeoutTest.java
diffstat 303 files changed, 63794 insertions(+), 15685 deletions(-) [+]
line wrap: on
line diff
--- a/THIRD_PARTY_README	Tue Oct 23 09:40:06 2012 -0700
+++ b/THIRD_PARTY_README	Tue Oct 23 09:41:52 2012 -0700
@@ -2,11 +2,11 @@
 -----------------------------
 
 %% This notice is provided with respect to ASM Bytecode Manipulation 
-Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7.
+Framework v4.0, which is included with JRE 8, and JDK 8.
 
 --- begin of LICENSE ---
 
-Copyright (c) 2000-2005 INRIA, France Telecom
+Copyright (c) 2000-2011 France TÚlÚcom
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
--- a/make/Makefile	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -233,7 +233,7 @@
 
 all build:: sanity-all post-sanity-all
 
-SUBDIRS       = tools java javax sun com
+SUBDIRS       = tools java javax sun com jdk
 ifeq ($(PLATFORM), macosx)
   SUBDIRS += apple
 endif
--- a/make/common/Release.gmk	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/common/Release.gmk	Tue Oct 23 09:41:52 2012 -0700
@@ -348,15 +348,15 @@
 	sun/tools/serialver	\
 	sun/tools/tree		\
 	sun/tools/util		\
-	sun/security/tools/JarBASE64Encoder.class \
-	sun/security/tools/JarSigner.class \
-	sun/security/tools/JarSignerParameters.class \
-	sun/security/tools/JarSignerResources.class \
-	sun/security/tools/JarSignerResources_ja.class \
-	sun/security/tools/JarSignerResources_zh_CN.class \
-	sun/security/tools/SignatureFile\$$Block.class \
-	sun/security/tools/SignatureFile.class \
-	sun/security/tools/TimestampedSigner.class \
+	sun/security/tools/jarsigner/JarBASE64Encoder.class \
+	sun/security/tools/jarsigner/Main.class \
+	sun/security/tools/jarsigner/JarSignerParameters.class \
+	sun/security/tools/jarsigner/Resources.class \
+	sun/security/tools/jarsigner/Resources_ja.class \
+	sun/security/tools/jarsigner/Resources_zh_CN.class \
+	sun/security/tools/jarsigner/SignatureFile\$$Block.class \
+	sun/security/tools/jarsigner/SignatureFile.class \
+	sun/security/tools/jarsigner/TimestampedSigner.class \
 	sun/rmi/rmic		\
 	sun/applet		\
 	sun/jvmstat		\
@@ -572,15 +572,15 @@
 	$(ECHO) "sun/tools/serialver/" >> $@
 	$(ECHO) "sun/tools/tree/" >> $@
 	$(ECHO) "sun/tools/util/" >> $@
-	$(ECHO) "sun/security/tools/JarBASE64Encoder.class" >> $@
-	$(ECHO) "sun/security/tools/JarSigner.class" >> $@
-	$(ECHO) "sun/security/tools/JarSignerParameters.class" >> $@
-	$(ECHO) "sun/security/tools/JarSignerResources.class" >> $@
-	$(ECHO) "sun/security/tools/JarSignerResources_ja.class" >> $@
-	$(ECHO) "sun/security/tools/JarSignerResources_zh_CN.class" >> $@
-	$(ECHO) "sun/security/tools/SignatureFile\$$Block.class" >> $@
-	$(ECHO) "sun/security/tools/SignatureFile.class" >> $@
-	$(ECHO) "sun/security/tools/TimestampedSigner.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/JarBASE64Encoder.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/Main.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/JarSignerParameters.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/Resources.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/Resources_ja.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/Resources_zh_CN.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/SignatureFile\$$Block.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/SignatureFile.class" >> $@
+	$(ECHO) "sun/security/tools/jarsigner/TimestampedSigner.class" >> $@
 	$(ECHO) "sun/security/provider/Sun.class" >> $@
 	$(ECHO) "sun/security/rsa/SunRsaSign.class" >> $@
 	$(ECHO) "sun/security/ssl/" >> $@
--- a/make/common/internal/Defs-jaxws.gmk	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/common/internal/Defs-jaxws.gmk	Tue Oct 23 09:41:52 2012 -0700
@@ -34,6 +34,10 @@
      javax/xml/ws \
      javax/jws \
      javax/annotation \
+     com/sun/org/glassfish \
+     com/sun/istack/internal \
+     com/sun/istack/internal/localization \
+     com/sun/istack/internal/logging \
      com/sun/xml/internal/bind \
      com/sun/xml/internal/fastinfoset \
      com/sun/xml/internal/messaging \
--- a/make/java/java/Makefile	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/java/java/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -64,13 +64,11 @@
 include Exportedfiles.gmk
 
 ifeq ($(PLATFORM),windows)
-FILES_java += 	java/io/Win32FileSystem.java \
-		java/io/WinNTFileSystem.java \
+FILES_java += 	java/io/WinNTFileSystem.java \
 		java/util/prefs/WindowsPreferences.java \
                 java/util/prefs/WindowsPreferencesFactory.java
 
 FILES_c    +=   ProcessImpl_md.c \
-		Win32FileSystem_md.c \
 		WinNTFileSystem_md.c \
 		canonicalize_md.c \
 		dirent_md.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,38 @@
+#
+# 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
+# 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.
+#
+
+#
+# Makefile for building all of java
+#
+
+BUILDDIR = ..
+PRODUCT = jdk
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = asm
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+	$(SUBDIRS-loop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/asm/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,40 @@
+#
+# 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
+# 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.
+#
+
+BUILDDIR = ../..
+PACKAGE = jdk.internal.org.objectweb.asm
+PRODUCT = jdk
+JAVAC_LINT_OPTIONS=-Xlint:all
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files to compile
+#
+AUTO_FILES_JAVA_DIRS = jdk/internal/org/objectweb/asm
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
--- a/make/jprt.properties	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/jprt.properties	Tue Oct 23 09:41:52 2012 -0700
@@ -77,20 +77,18 @@
     ${jprt.my.test.target.set:TESTNAME=jdk_util},               \
     ${jprt.my.test.target.set:TESTNAME=jdk_io},                 \
     ${jprt.my.test.target.set:TESTNAME=jdk_net},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_nio1},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_nio2},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_nio3},               \
+    ${jprt.my.test.target.set:TESTNAME=jdk_nio},                \
     ${jprt.my.test.target.set:TESTNAME=jdk_security1},          \
     ${jprt.my.test.target.set:TESTNAME=jdk_security2},          \
     ${jprt.my.test.target.set:TESTNAME=jdk_security3},          \
     ${jprt.my.test.target.set:TESTNAME=jdk_rmi},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_management1},        \
-    ${jprt.my.test.target.set:TESTNAME=jdk_management2},        \
+    ${jprt.my.test.target.set:TESTNAME=jdk_management},         \
+    ${jprt.my.test.target.set:TESTNAME=jdk_jmx},                \
     ${jprt.my.test.target.set:TESTNAME=jdk_text},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_tools1},             \
-    ${jprt.my.test.target.set:TESTNAME=jdk_tools2},             \
+    ${jprt.my.test.target.set:TESTNAME=jdk_tools},              \
+    ${jprt.my.test.target.set:TESTNAME=jdk_jdi},                \
     ${jprt.my.test.target.set:TESTNAME=jdk_jfr},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_misc}
+    ${jprt.my.test.target.set:TESTNAME=jdk_other}
 
 # All vm test targets (testset=all)
 jprt.vm.all.test.targets=                                       \
--- a/make/launchers/Makefile	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/launchers/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -58,7 +58,7 @@
 $(call make-launcher, extcheck, com.sun.tools.extcheck.Main, , )
 $(call make-launcher, idlj, com.sun.tools.corba.se.idl.toJavaPortable.Compile, , )
 $(call make-launcher, jar, sun.tools.jar.Main, , )
-$(call make-launcher, jarsigner, sun.security.tools.JarSigner, , )
+$(call make-launcher, jarsigner, sun.security.tools.jarsigner.Main, , )
 $(call make-launcher, javac, com.sun.tools.javac.Main, , )
 $(call make-launcher, javadoc, com.sun.tools.javadoc.Main, , )
 $(call make-launcher, javah, com.sun.tools.javah.Main, , )
--- a/make/sun/security/tools/Makefile	Tue Oct 23 09:40:06 2012 -0700
+++ b/make/sun/security/tools/Makefile	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -37,7 +37,7 @@
 # Resources
 #
 LOCALE_SET_DEFINITION = jdk
-RESOURCE_BUNDLES_JAVA = sun/security/tools/JarSignerResources.java
+RESOURCE_BUNDLES_JAVA = sun/security/tools/jarsigner/Resources.java
 
 #
 # Rules
@@ -45,7 +45,7 @@
 include $(BUILDDIR)/common/Classes.gmk
 
 build:
-	$(call make-launcher, keytool, sun.security.tools.KeyTool, , )
+	$(call make-launcher, keytool, sun.security.tools.keytool.Main, , )
 ifndef BUILD_HEADLESS_ONLY
 	$(call make-launcher, policytool, sun.security.tools.policytool.PolicyTool, , )
 endif
--- a/makefiles/CompileLaunchers.gmk	Tue Oct 23 09:40:06 2012 -0700
+++ b/makefiles/CompileLaunchers.gmk	Tue Oct 23 09:41:52 2012 -0700
@@ -232,7 +232,7 @@
     -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jar.Main"$(COMMA) }'))
 
 $(eval $(call SetupLauncher,jarsigner,\
-    -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.JarSigner"$(COMMA) }'))
+    -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.jarsigner.Main"$(COMMA) }'))
 
 $(eval $(call SetupLauncher,javac,\
     -DEXPAND_CLASSPATH_WILDCARDS \
@@ -310,7 +310,7 @@
     -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jstatd.Jstatd"$(COMMA) }'))
 
 $(eval $(call SetupLauncher,keytool,\
-    -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.KeyTool"$(COMMA) }'))
+    -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.keytool.Main"$(COMMA) }'))
 
 $(eval $(call SetupLauncher,native2ascii,\
     -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.native2ascii.Main"$(COMMA) }'))
--- a/makefiles/CompileNativeLibraries.gmk	Tue Oct 23 09:40:06 2012 -0700
+++ b/makefiles/CompileNativeLibraries.gmk	Tue Oct 23 09:41:52 2012 -0700
@@ -209,7 +209,6 @@
 else
 	LIBJAVA_EXCLUDE_FILES += \
 		ProcessImpl_md.c \
-		Win32FileSystem_md.c \
 		WinNTFileSystem_md.c \
 		dirent_md.c \
 		WindowsPreferences.c \
--- a/makefiles/CreateJars.gmk	Tue Oct 23 09:40:06 2012 -0700
+++ b/makefiles/CreateJars.gmk	Tue Oct 23 09:41:52 2012 -0700
@@ -131,15 +131,15 @@
 	sun/tools/serialver \
 	sun/tools/tree \
 	sun/tools/util \
-	sun/security/tools/JarBASE64Encoder.class \
-	sun/security/tools/JarSigner.class \
-	sun/security/tools/JarSignerParameters.class \
-	sun/security/tools/JarSignerResources.class \
-	sun/security/tools/JarSignerResources_ja.class \
-	sun/security/tools/JarSignerResources_zh_CN.class \
-	sun/security/tools/SignatureFile\$$$$Block.class \
-	sun/security/tools/SignatureFile.class \
-	sun/security/tools/TimestampedSigner.class \
+	sun/security/tools/jarsigner/JarBASE64Encoder.class \
+	sun/security/tools/jarsigner/Main.class \
+	sun/security/tools/jarsigner/JarSignerParameters.class \
+	sun/security/tools/jarsigner/Resources.class \
+	sun/security/tools/jarsigner/Resources_ja.class \
+	sun/security/tools/jarsigner/Resources_zh_CN.class \
+	sun/security/tools/jarsigner/SignatureFile\$$$$Block.class \
+	sun/security/tools/jarsigner/SignatureFile.class \
+	sun/security/tools/jarsigner/TimestampedSigner.class \
 	sun/security/provider/Sun.class \
 	sun/security/rsa/SunRsaSign.class \
 	sun/security/ssl \
--- a/src/macosx/classes/java/util/prefs/MacOSXPreferences.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/macosx/classes/java/util/prefs/MacOSXPreferences.java	Tue Oct 23 09:41:52 2012 -0700
@@ -100,7 +100,7 @@
         else
             this.isUser = isUserNode();
         path = isRoot ? absolutePath() : absolutePath() + "/";
-        file = cfFileForNode(isUser);
+        file = cfFileForNode(this.isUser);
         if (isNew)
             newNode = isNew;
         else
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java	Tue Oct 23 09:41:52 2012 -0700
@@ -157,7 +157,8 @@
     volatile IOException closureReason = null;
     volatile boolean useable = true;  // is Connection still useable
 
-    private int readTimeout;
+    int readTimeout;
+    int connectTimeout;
 
     // true means v3; false means v2
     // Called in LdapClient.authenticate() (which is synchronized)
@@ -187,6 +188,7 @@
         this.port = port;
         this.parent = parent;
         this.readTimeout = readTimeout;
+        this.connectTimeout = connectTimeout;
 
         if (trace != null) {
             traceFile = trace;
--- a/src/share/classes/com/sun/jndi/ldap/LdapClient.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/LdapClient.java	Tue Oct 23 09:41:52 2012 -0700
@@ -150,149 +150,155 @@
         String authMechanism, Control[] ctls,  Hashtable<?,?> env)
         throws NamingException {
 
-        authenticateCalled = true;
+        int readTimeout = conn.readTimeout;
+        conn.readTimeout = conn.connectTimeout;
+        LdapResult res = null;
 
         try {
-            ensureOpen();
-        } catch (IOException e) {
-            NamingException ne = new CommunicationException();
-            ne.setRootCause(e);
-            throw ne;
-        }
+            authenticateCalled = true;
 
-        switch (version) {
-        case LDAP_VERSION3_VERSION2:
-        case LDAP_VERSION3:
-            isLdapv3 = true;
-            break;
-        case LDAP_VERSION2:
-            isLdapv3 = false;
-            break;
-        default:
-            throw new CommunicationException("Protocol version " + version +
-                " not supported");
-        }
+            try {
+                ensureOpen();
+            } catch (IOException e) {
+                NamingException ne = new CommunicationException();
+                ne.setRootCause(e);
+                throw ne;
+            }
 
-        LdapResult res = null;
+            switch (version) {
+            case LDAP_VERSION3_VERSION2:
+            case LDAP_VERSION3:
+                isLdapv3 = true;
+                break;
+            case LDAP_VERSION2:
+                isLdapv3 = false;
+                break;
+            default:
+                throw new CommunicationException("Protocol version " + version +
+                    " not supported");
+            }
 
-        if (authMechanism.equalsIgnoreCase("none") ||
-            authMechanism.equalsIgnoreCase("anonymous")) {
+            if (authMechanism.equalsIgnoreCase("none") ||
+                authMechanism.equalsIgnoreCase("anonymous")) {
 
-            // Perform LDAP bind if we are reauthenticating, using LDAPv2,
-            // supporting failover to LDAPv2, or controls have been supplied.
-            if (!initial ||
-                (version == LDAP_VERSION2) ||
-                (version == LDAP_VERSION3_VERSION2) ||
-                ((ctls != null) && (ctls.length > 0))) {
+                // Perform LDAP bind if we are reauthenticating, using LDAPv2,
+                // supporting failover to LDAPv2, or controls have been supplied.
+                if (!initial ||
+                    (version == LDAP_VERSION2) ||
+                    (version == LDAP_VERSION3_VERSION2) ||
+                    ((ctls != null) && (ctls.length > 0))) {
+                    try {
+                        // anonymous bind; update name/pw for LDAPv2 retry
+                        res = ldapBind(name=null, (byte[])(pw=null), ctls, null,
+                            false);
+                        if (res.status == LdapClient.LDAP_SUCCESS) {
+                            conn.setBound();
+                        }
+                    } catch (IOException e) {
+                        NamingException ne =
+                            new CommunicationException("anonymous bind failed: " +
+                            conn.host + ":" + conn.port);
+                        ne.setRootCause(e);
+                        throw ne;
+                    }
+                } else {
+                    // Skip LDAP bind for LDAPv3 anonymous bind
+                    res = new LdapResult();
+                    res.status = LdapClient.LDAP_SUCCESS;
+                }
+            } else if (authMechanism.equalsIgnoreCase("simple")) {
+                // simple authentication
+                byte[] encodedPw = null;
                 try {
-                    // anonymous bind; update name/pw for LDAPv2 retry
-                    res = ldapBind(name=null, (byte[])(pw=null), ctls, null,
-                        false);
+                    encodedPw = encodePassword(pw, isLdapv3);
+                    res = ldapBind(name, encodedPw, ctls, null, false);
                     if (res.status == LdapClient.LDAP_SUCCESS) {
                         conn.setBound();
                     }
                 } catch (IOException e) {
                     NamingException ne =
-                        new CommunicationException("anonymous bind failed: " +
+                        new CommunicationException("simple bind failed: " +
+                            conn.host + ":" + conn.port);
+                    ne.setRootCause(e);
+                    throw ne;
+                } finally {
+                    // If pw was copied to a new array, clear that array as
+                    // a security precaution.
+                    if (encodedPw != pw && encodedPw != null) {
+                        for (int i = 0; i < encodedPw.length; i++) {
+                            encodedPw[i] = 0;
+                        }
+                    }
+                }
+            } else if (isLdapv3) {
+                // SASL authentication
+                try {
+                    res = LdapSasl.saslBind(this, conn, conn.host, name, pw,
+                        authMechanism, env, ctls);
+                    if (res.status == LdapClient.LDAP_SUCCESS) {
+                        conn.setBound();
+                    }
+                } catch (IOException e) {
+                    NamingException ne =
+                        new CommunicationException("SASL bind failed: " +
                         conn.host + ":" + conn.port);
                     ne.setRootCause(e);
                     throw ne;
                 }
             } else {
-                // Skip LDAP bind for LDAPv3 anonymous bind
-                res = new LdapResult();
-                res.status = LdapClient.LDAP_SUCCESS;
+                throw new AuthenticationNotSupportedException(authMechanism);
             }
-        } else if (authMechanism.equalsIgnoreCase("simple")) {
-            // simple authentication
-            byte[] encodedPw = null;
-            try {
-                encodedPw = encodePassword(pw, isLdapv3);
-                res = ldapBind(name, encodedPw, ctls, null, false);
-                if (res.status == LdapClient.LDAP_SUCCESS) {
-                    conn.setBound();
-                }
-            } catch (IOException e) {
-                NamingException ne =
-                    new CommunicationException("simple bind failed: " +
-                        conn.host + ":" + conn.port);
-                ne.setRootCause(e);
-                throw ne;
-            } finally {
-                // If pw was copied to a new array, clear that array as
-                // a security precaution.
-                if (encodedPw != pw && encodedPw != null) {
-                    for (int i = 0; i < encodedPw.length; i++) {
-                        encodedPw[i] = 0;
+
+            //
+            // re-try login using v2 if failing over
+            //
+            if (initial &&
+                (res.status == LdapClient.LDAP_PROTOCOL_ERROR) &&
+                (version == LdapClient.LDAP_VERSION3_VERSION2) &&
+                (authMechanism.equalsIgnoreCase("none") ||
+                    authMechanism.equalsIgnoreCase("anonymous") ||
+                    authMechanism.equalsIgnoreCase("simple"))) {
+
+                byte[] encodedPw = null;
+                try {
+                    isLdapv3 = false;
+                    encodedPw = encodePassword(pw, false);
+                    res = ldapBind(name, encodedPw, ctls, null, false);
+                    if (res.status == LdapClient.LDAP_SUCCESS) {
+                        conn.setBound();
+                    }
+                } catch (IOException e) {
+                    NamingException ne =
+                        new CommunicationException(authMechanism + ":" +
+                            conn.host +     ":" + conn.port);
+                    ne.setRootCause(e);
+                    throw ne;
+                } finally {
+                    // If pw was copied to a new array, clear that array as
+                    // a security precaution.
+                    if (encodedPw != pw && encodedPw != null) {
+                        for (int i = 0; i < encodedPw.length; i++) {
+                            encodedPw[i] = 0;
+                        }
                     }
                 }
             }
-        } else if (isLdapv3) {
-            // SASL authentication
-            try {
-                res = LdapSasl.saslBind(this, conn, conn.host, name, pw,
-                    authMechanism, env, ctls);
-                if (res.status == LdapClient.LDAP_SUCCESS) {
-                    conn.setBound();
-                }
-            } catch (IOException e) {
-                NamingException ne =
-                    new CommunicationException("SASL bind failed: " +
-                    conn.host + ":" + conn.port);
-                ne.setRootCause(e);
-                throw ne;
+
+            // principal name not found
+            // (map NameNotFoundException to AuthenticationException)
+            // %%% This is a workaround for Netscape servers returning
+            // %%% no such object when the principal name is not found
+            // %%% Note that when this workaround is applied, it does not allow
+            // %%% response controls to be recorded by the calling context
+            if (res.status == LdapClient.LDAP_NO_SUCH_OBJECT) {
+                throw new AuthenticationException(
+                    getErrorMessage(res.status, res.errorMessage));
             }
-        } else {
-            throw new AuthenticationNotSupportedException(authMechanism);
+            conn.setV3(isLdapv3);
+            return res;
+        } finally {
+            conn.readTimeout = readTimeout;
         }
-
-        //
-        // re-try login using v2 if failing over
-        //
-        if (initial &&
-            (res.status == LdapClient.LDAP_PROTOCOL_ERROR) &&
-            (version == LdapClient.LDAP_VERSION3_VERSION2) &&
-            (authMechanism.equalsIgnoreCase("none") ||
-                authMechanism.equalsIgnoreCase("anonymous") ||
-                authMechanism.equalsIgnoreCase("simple"))) {
-
-            byte[] encodedPw = null;
-            try {
-                isLdapv3 = false;
-                encodedPw = encodePassword(pw, false);
-                res = ldapBind(name, encodedPw, ctls, null, false);
-                if (res.status == LdapClient.LDAP_SUCCESS) {
-                    conn.setBound();
-                }
-            } catch (IOException e) {
-                NamingException ne =
-                    new CommunicationException(authMechanism + ":" +
-                        conn.host +     ":" + conn.port);
-                ne.setRootCause(e);
-                throw ne;
-            } finally {
-                // If pw was copied to a new array, clear that array as
-                // a security precaution.
-                if (encodedPw != pw && encodedPw != null) {
-                    for (int i = 0; i < encodedPw.length; i++) {
-                        encodedPw[i] = 0;
-                    }
-                }
-            }
-        }
-
-        // principal name not found
-        // (map NameNotFoundException to AuthenticationException)
-        // %%% This is a workaround for Netscape servers returning
-        // %%% no such object when the principal name is not found
-        // %%% Note that when this workaround is applied, it does not allow
-        // %%% response controls to be recorded by the calling context
-        if (res.status == LdapClient.LDAP_NO_SUCH_OBJECT) {
-            throw new AuthenticationException(
-                getErrorMessage(res.status, res.errorMessage));
-        }
-        conn.setV3(isLdapv3);
-        return res;
     }
 
     /**
--- a/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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
@@ -1746,12 +1746,7 @@
 
         // convert to a Double and compare to zero
         try {
-            Double d = new Double(value.toString());
-            if (d.compareTo(new Double((double)0)) == 0) {
-                return false;
-            } else {
-                return true;
-            }
+            return Double.compare(Double.parseDouble(value.toString()), 0) != 0;
         } catch (NumberFormatException ex) {
             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
                   new Object[] {value.toString().trim(), columnIndex}));
@@ -2039,6 +2034,7 @@
      *            the cursor is not on a valid row, or this method fails
      * @deprecated
      */
+    @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
         Object value;
         BigDecimal bDecimal, retVal;
@@ -2374,6 +2370,7 @@
      * @throws SQLException if an error occurs
      * @deprecated
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
         // always free an old stream
         unicodeStream = null;
@@ -2643,6 +2640,7 @@
      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
      *             method instead
      */
+    @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
         return getBigDecimal(getColIdxByName(columnName), scale);
     }
@@ -2774,6 +2772,7 @@
      *            this rowset's rows or its insert row
      * @deprecated use the method <code>getCharacterStream</code> instead
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
         return getUnicodeStream(getColIdxByName(columnName));
     }
@@ -4428,7 +4427,7 @@
         // make sure the cursor is on a valid row
         checkCursor();
 
-        Object obj = convertNumeric(new Float(x),
+        Object obj = convertNumeric(Float.valueOf(x),
         java.sql.Types.REAL,
         RowSetMD.getColumnType(columnIndex));
 
@@ -4463,7 +4462,7 @@
         checkIndex(columnIndex);
         // make sure the cursor is on a valid row
         checkCursor();
-        Object obj = convertNumeric(new Double(x),
+        Object obj = convertNumeric(Double.valueOf(x),
         java.sql.Types.DOUBLE,
         RowSetMD.getColumnType(columnIndex));
 
--- a/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -839,7 +839,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Float(x) , columnIndex);
+            bool = p.evaluate(Float.valueOf(x), columnIndex);
 
             if(!bool) {
                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -906,7 +906,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Double(x) , columnIndex);
+            bool = p.evaluate(Double.valueOf(x) , columnIndex);
 
             if(!bool) {
                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
--- a/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1016,6 +1016,7 @@
      *            prepared statement, and result set
      * @deprecated
      */
+    @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
         checkState();
 
@@ -1154,6 +1155,7 @@
      * @deprecated use <code>getCharacterStream</code> in place of
      *              <code>getUnicodeStream</code>
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
         checkState();
 
@@ -1336,6 +1338,7 @@
      *            prepared statement, and result set
      * @deprecated
      */
+    @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
         return getBigDecimal(findColumn(columnName), scale);
     }
@@ -1461,6 +1464,7 @@
      *            prepared statement, and result set
      * @deprecated
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
         return getUnicodeStream(findColumn(columnName));
     }
--- a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1153,6 +1153,7 @@
      *            the cursor is not on a valid row, or this method fails
      * @deprecated
      */
+    @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
         return crsInternal.getBigDecimal(columnIndex);
     }
@@ -1264,6 +1265,7 @@
      * @throws SQLException if an error occurs
      * @deprecated
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
         return crsInternal.getUnicodeStream(columnIndex);
     }
@@ -1436,6 +1438,7 @@
      * @deprecated use the method <code>getBigDecimal(String columnName)</code>
      *             instead
      */
+    @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
         return crsInternal.getBigDecimal(columnName);
     }
@@ -1552,6 +1555,7 @@
      *            this rowset's rows or its insert row
      * @deprecated use the method <code>getCharacterStream</code> instead
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
         return crsInternal.getUnicodeStream(columnName);
     }
--- a/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1288,6 +1288,7 @@
      *            the cursor is not on a valid row, or this method fails
      * @deprecated
      */
+    @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
        throw new UnsupportedOperationException();
     }
@@ -1424,6 +1425,7 @@
      * @throws SQLException if an error occurs
      * @deprecated
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
        throw new UnsupportedOperationException();
     }
@@ -1653,6 +1655,7 @@
      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
      *             method instead
      */
+    @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
         throw new UnsupportedOperationException();
     }
@@ -1784,6 +1787,7 @@
      *            this rowset's rows or its insert row
      * @deprecated use the method <code>getCharacterStream</code> instead
      */
+    @Deprecated
     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
         throw new UnsupportedOperationException();
     }
--- a/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java	Tue Oct 23 09:41:52 2012 -0700
@@ -802,7 +802,7 @@
 
         if (doNotPrompt) {
             throw new LoginException
-                ("Unable to obtain Princpal Name for authentication ");
+                ("Unable to obtain Principal Name for authentication ");
         } else {
             if (callbackHandler == null)
                 throw new LoginException("No CallbackHandler "
--- a/src/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -52,6 +52,7 @@
     private boolean shut_wr = false;
 
     private SocketInputStream socketInputStream = null;
+    private SocketOutputStream socketOutputStream = null;
 
     /* number of threads using the FileDescriptor */
     protected int fdUseCount = 0;
@@ -436,7 +437,10 @@
         if (shut_wr) {
             throw new IOException("Socket output is shutdown");
         }
-        return new SocketOutputStream(this);
+        if (socketOutputStream == null) {
+            socketOutputStream = new SocketOutputStream(this);
+        }
+        return socketOutputStream;
     }
 
     void setFileDescriptor(FileDescriptor fd) {
--- a/src/share/classes/java/net/ProxySelector.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/net/ProxySelector.java	Tue Oct 23 09:41:52 2012 -0700
@@ -127,7 +127,6 @@
      * <UL>
      * <LI>http URI for http connections</LI>
      * <LI>https URI for https connections
-     * <LI>ftp URI for ftp connections</LI>
      * <LI><code>socket://host:port</code><br>
      *     for tcp client sockets connections</LI>
      * </UL>
--- a/src/share/classes/java/net/URL.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/net/URL.java	Tue Oct 23 09:41:52 2012 -0700
@@ -274,7 +274,7 @@
      * <p>Protocol handlers for the following protocols are guaranteed
      * to exist on the search path :-
      * <blockquote><pre>
-     *     http, https, ftp, file, and jar
+     *     http, https, file, and jar
      * </pre></blockquote>
      * Protocol handlers for additional protocols may also be
      * available.
--- a/src/share/classes/java/net/URLStreamHandler.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/net/URLStreamHandler.java	Tue Oct 23 09:41:52 2012 -0700
@@ -37,8 +37,7 @@
  * The abstract class <code>URLStreamHandler</code> is the common
  * superclass for all stream protocol handlers. A stream protocol
  * handler knows how to make a connection for a particular protocol
- * type, such as <code>http</code>, <code>ftp</code>, or
- * <code>gopher</code>.
+ * type, such as <code>http</code> or <code>https</code>.
  * <p>
  * In most cases, an instance of a <code>URLStreamHandler</code>
  * subclass is not created directly by an application. Rather, the
--- a/src/share/classes/java/net/package.html	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/net/package.html	Tue Oct 23 09:41:52 2012 -0700
@@ -72,7 +72,7 @@
 <ul>
       <li>{@link java.net.URI} is the class representing a Universal Resource Identifier, as specified in RFC 2396. As the name indicates, this is just an Identifier and doesn't provide directly the means to access the resource.</li>
       <li>{@link java.net.URL} is the class representing a Universal Resource Locator, which is both an older concept for URIs and a means to access the resources.</li>
-      <li>{@link java.net.URLConnection} is created from a URL and is the communication link used to access the resource pointed by the URL. This abstract class will delegate most of the work to the underlying protocol handlers like http or ftp.</li>
+      <li>{@link java.net.URLConnection} is created from a URL and is the communication link used to access the resource pointed by the URL. This abstract class will delegate most of the work to the underlying protocol handlers like http or https.</li>
       <li>{@link java.net.HttpURLConnection} is a subclass of URLConnection and provides some additional functionalities specific to the HTTP protocol.</li>
 </ul>
 <p>The recommended usage is to use {@link java.net.URI} to identify resources, then convert it into a {@link java.net.URL} when it is time to access the resource. From that URL, you can either get the {@link java.net.URLConnection} for fine control, or get directly the InputStream.<p>
--- a/src/share/classes/java/sql/CallableStatement.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/sql/CallableStatement.java	Tue Oct 23 09:41:52 2012 -0700
@@ -295,6 +295,7 @@
      *             or <code>getBigDecimal(String parameterName)</code>
      * @see #setBigDecimal
      */
+    @Deprecated
     BigDecimal getBigDecimal(int parameterIndex, int scale)
         throws SQLException;
 
--- a/src/share/classes/java/sql/Date.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/sql/Date.java	Tue Oct 23 09:41:52 2012 -0700
@@ -51,6 +51,7 @@
      * @param day 1 to 31
      * @deprecated instead use the constructor <code>Date(long date)</code>
      */
+    @Deprecated
     public Date(int year, int month, int day) {
         super(year, month, day);
     }
@@ -179,6 +180,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setHours
     */
+    @Deprecated
     public int getHours() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -191,6 +193,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setMinutes
     */
+    @Deprecated
     public int getMinutes() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -203,6 +206,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setSeconds
     */
+    @Deprecated
     public int getSeconds() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -215,6 +219,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getHours
     */
+    @Deprecated
     public void setHours(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -227,6 +232,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getMinutes
     */
+    @Deprecated
     public void setMinutes(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -239,6 +245,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getSeconds
     */
+    @Deprecated
     public void setSeconds(int i) {
         throw new java.lang.IllegalArgumentException();
     }
--- a/src/share/classes/java/sql/DriverManager.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/sql/DriverManager.java	Tue Oct 23 09:41:52 2012 -0700
@@ -412,13 +412,14 @@
      * method throws a <code>java.lang.SecurityException</code>.
      *
      * @param out the new logging/tracing PrintStream; to disable, set to <code>null</code>
-     * @deprecated
+     * @deprecated Use {@code setLogWriter}
      * @throws SecurityException if a security manager exists and its
      *    <code>checkPermission</code> method denies setting the log stream
      *
      * @see SecurityManager#checkPermission
      * @see #getLogStream
      */
+    @Deprecated
     public static void setLogStream(java.io.PrintStream out) {
 
         SecurityManager sec = System.getSecurityManager();
@@ -438,9 +439,10 @@
      * and all drivers.
      *
      * @return the logging/tracing PrintStream; if disabled, is <code>null</code>
-     * @deprecated
+     * @deprecated  Use {@code getLogWriter}
      * @see #setLogStream
      */
+    @Deprecated
     public static java.io.PrintStream getLogStream() {
         return logStream;
     }
--- a/src/share/classes/java/sql/PreparedStatement.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/sql/PreparedStatement.java	Tue Oct 23 09:41:52 2012 -0700
@@ -342,8 +342,9 @@
      * this method is called on a closed <code>PreparedStatement</code>
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method
-     * @deprecated
+     * @deprecated Use {@code setCharacterStream}
      */
+    @Deprecated
     void setUnicodeStream(int parameterIndex, java.io.InputStream x,
                           int length) throws SQLException;
 
--- a/src/share/classes/java/sql/ResultSet.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/sql/ResultSet.java	Tue Oct 23 09:41:52 2012 -0700
@@ -356,8 +356,10 @@
      *            called on a closed result set
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method
-     * @deprecated
+     * @deprecated Use {@code getBigDecimal(int columnIndex)}
+     *             or {@code getBigDecimal(String columnLabel)}
      */
+    @Deprecated
     BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException;
 
     /**
@@ -477,6 +479,7 @@
      * @deprecated use <code>getCharacterStream</code> in place of
      *              <code>getUnicodeStream</code>
      */
+    @Deprecated
     java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException;
 
     /**
@@ -641,8 +644,10 @@
      *            called on a closed result set
      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
      * this method
-     * @deprecated
+     * @deprecated Use {@code getBigDecimal(int columnIndex)}
+     *             or {@code getBigDecimal(String columnLabel)}
      */
+    @Deprecated
     BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException;
 
     /**
@@ -760,6 +765,7 @@
      * this method
      * @deprecated use <code>getCharacterStream</code> instead
      */
+    @Deprecated
     java.io.InputStream getUnicodeStream(String columnLabel) throws SQLException;
 
     /**
--- a/src/share/classes/java/text/DateFormatSymbols.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/text/DateFormatSymbols.java	Tue Oct 23 09:41:52 2012 -0700
@@ -45,6 +45,7 @@
 import java.text.spi.DateFormatSymbolsProvider;
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.ResourceBundle;
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
@@ -366,6 +367,7 @@
      */
     public void setEras(String[] newEras) {
         eras = Arrays.copyOf(newEras, newEras.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -393,6 +395,7 @@
      */
     public void setMonths(String[] newMonths) {
         months = Arrays.copyOf(newMonths, newMonths.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -420,6 +423,7 @@
      */
     public void setShortMonths(String[] newShortMonths) {
         shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -439,6 +443,7 @@
      */
     public void setWeekdays(String[] newWeekdays) {
         weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -458,6 +463,7 @@
      */
     public void setShortWeekdays(String[] newShortWeekdays) {
         shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -474,6 +480,7 @@
      */
     public void setAmPmStrings(String[] newAmpms) {
         ampms = Arrays.copyOf(newAmpms, newAmpms.length);
+        cachedHashCode = 0;
     }
 
     /**
@@ -558,6 +565,7 @@
         }
         zoneStrings = aCopy;
         isZoneStringsSet = true;
+        cachedHashCode = 0;
     }
 
     /**
@@ -576,6 +584,7 @@
     public void setLocalPatternChars(String newLocalPatternChars) {
         // Call toString() to throw an NPE in case the argument is null
         localPatternChars = newLocalPatternChars.toString();
+        cachedHashCode = 0;
     }
 
     /**
@@ -597,12 +606,23 @@
      * Override hashCode.
      * Generates a hash code for the DateFormatSymbols object.
      */
+    @Override
     public int hashCode() {
-        int hashcode = 0;
-        String[][] zoneStrings = getZoneStringsWrapper();
-        for (int index = 0; index < zoneStrings[0].length; ++index)
-            hashcode ^= zoneStrings[0][index].hashCode();
-        return hashcode;
+        int hashCode = cachedHashCode;
+        if (hashCode == 0) {
+            hashCode = 5;
+            hashCode = 11 * hashCode + Arrays.hashCode(eras);
+            hashCode = 11 * hashCode + Arrays.hashCode(months);
+            hashCode = 11 * hashCode + Arrays.hashCode(shortMonths);
+            hashCode = 11 * hashCode + Arrays.hashCode(weekdays);
+            hashCode = 11 * hashCode + Arrays.hashCode(shortWeekdays);
+            hashCode = 11 * hashCode + Arrays.hashCode(ampms);
+            hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
+            hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
+            cachedHashCode = hashCode;
+        }
+
+        return hashCode;
     }
 
     /**
@@ -641,6 +661,11 @@
 
     private transient int lastZoneIndex = 0;
 
+    /**
+     * Cached hash code
+     */
+    transient volatile int cachedHashCode = 0;
+
     private void initializeData(Locale desiredLocale) {
         locale = desiredLocale;
 
@@ -782,6 +807,7 @@
             dst.zoneStrings = null;
         }
         dst.localPatternChars = src.localPatternChars;
+        dst.cachedHashCode = 0;
     }
 
     /**
--- a/src/share/classes/java/util/Hashtable.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/Hashtable.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1059,7 +1059,7 @@
         }
 
         public int hashCode() {
-            return hash ^ (value==null ? 0 : value.hashCode());
+            return (Objects.hashCode(key) ^ Objects.hashCode(value));
         }
 
         public String toString() {
--- a/src/share/classes/java/util/Properties.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/Properties.java	Tue Oct 23 09:41:52 2012 -0700
@@ -81,8 +81,9 @@
  * <p> The {@link #loadFromXML(InputStream)} and {@link
  * #storeToXML(OutputStream, String, String)} methods load and store properties
  * in a simple XML format.  By default the UTF-8 character encoding is used,
- * however a specific encoding may be specified if required.  An XML properties
- * document has the following DOCTYPE declaration:
+ * however a specific encoding may be specified if required. Implementations
+ * are required to support UTF-8 and UTF-16 and may support other encodings.
+ * An XML properties document has the following DOCTYPE declaration:
  *
  * <pre>
  * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
@@ -853,23 +854,30 @@
      * Furthermore, the document must satisfy the properties DTD described
      * above.
      *
+     * <p> An implementation is required to read XML documents that use the
+     * "{@code UTF-8}" or "{@code UTF-16}" encoding. An implementation may
+     * support additional encodings.
+     *
      * <p>The specified stream is closed after this method returns.
      *
      * @param in the input stream from which to read the XML document.
      * @throws IOException if reading from the specified input stream
      *         results in an <tt>IOException</tt>.
+     * @throws java.io.UnsupportedEncodingException if the document's encoding
+     *         declaration can be read and it specifies an encoding that is not
+     *         supported
      * @throws InvalidPropertiesFormatException Data on input stream does not
      *         constitute a valid XML document with the mandated document type.
      * @throws NullPointerException if {@code in} is null.
      * @see    #storeToXML(OutputStream, String, String)
+     * @see    <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
+     *         Encoding in Entities</a>
      * @since 1.5
      */
     public synchronized void loadFromXML(InputStream in)
         throws IOException, InvalidPropertiesFormatException
     {
-        if (in == null)
-            throw new NullPointerException();
-        XmlSupport.load(this, in);
+        XmlSupport.load(this, Objects.requireNonNull(in));
         in.close();
     }
 
@@ -896,8 +904,6 @@
     public void storeToXML(OutputStream os, String comment)
         throws IOException
     {
-        if (os == null)
-            throw new NullPointerException();
         storeToXML(os, comment, "UTF-8");
     }
 
@@ -910,9 +916,13 @@
      * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
      * </pre>
      *
-     *<p>If the specified comment is {@code null} then no comment
+     * <p>If the specified comment is {@code null} then no comment
      * will be stored in the document.
      *
+     * <p> An implementation is required to support writing of XML documents
+     * that use the "{@code UTF-8}" or "{@code UTF-16}" encoding. An
+     * implementation may support additional encodings.
+     *
      * <p>The specified stream remains open after this method returns.
      *
      * @param os        the output stream on which to emit the XML document.
@@ -924,20 +934,23 @@
      *
      * @throws IOException if writing to the specified output stream
      *         results in an <tt>IOException</tt>.
+     * @throws java.io.UnsupportedEncodingException if the encoding is not
+     *         supported by the implementation.
      * @throws NullPointerException if {@code os} is {@code null},
      *         or if {@code encoding} is {@code null}.
      * @throws ClassCastException  if this {@code Properties} object
      *         contains any keys or values that are not
      *         {@code Strings}.
      * @see    #loadFromXML(InputStream)
+     * @see    <a href="http://www.w3.org/TR/REC-xml/#charencoding">Character
+     *         Encoding in Entities</a>
      * @since 1.5
      */
     public void storeToXML(OutputStream os, String comment, String encoding)
         throws IOException
     {
-        if (os == null)
-            throw new NullPointerException();
-        XmlSupport.save(this, os, comment, encoding);
+        XmlSupport.save(this, Objects.requireNonNull(os), comment,
+                        Objects.requireNonNull(encoding));
     }
 
     /**
--- a/src/share/classes/java/util/ServiceLoader.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/ServiceLoader.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, 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
@@ -214,7 +214,7 @@
 
     private ServiceLoader(Class<S> svc, ClassLoader cl) {
         service = Objects.requireNonNull(svc, "Service interface cannot be null");
-        loader = cl;
+        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
         reload();
     }
 
--- a/src/share/classes/java/util/TimeZone.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/TimeZone.java	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -719,15 +719,16 @@
      * Returns the default TimeZone in an AppContext if any AppContext
      * has ever used. null is returned if any AppContext hasn't been
      * used or if the AppContext doesn't have the default TimeZone.
+     *
+     * Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
+     * been loaded. If so, it implies that AWTSecurityManager is not our
+     * SecurityManager and we can use a local static variable.
+     * This works around a build time issue.
      */
-    private synchronized static TimeZone getDefaultInAppContext() {
+    private static TimeZone getDefaultInAppContext() {
         // JavaAWTAccess provides access implementation-private methods without using reflection.
         JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess();
 
-        // Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
-        // been loaded. If so, it implies that AWTSecurityManager is not our
-        // SecurityManager and we can use a local static variable.
-        // This works around a build time issue.
         if (javaAWTAccess == null) {
             return mainAppContextDefault;
         } else {
@@ -749,15 +750,16 @@
      * tz. null is handled special: do nothing if any AppContext
      * hasn't been used, remove the default TimeZone in the
      * AppContext otherwise.
+     *
+     * Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
+     * been loaded. If so, it implies that AWTSecurityManager is not our
+     * SecurityManager and we can use a local static variable.
+     * This works around a build time issue.
      */
-    private synchronized static void setDefaultInAppContext(TimeZone tz) {
+    private static void setDefaultInAppContext(TimeZone tz) {
         // JavaAWTAccess provides access implementation-private methods without using reflection.
         JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess();
 
-        // Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
-        // been loaded. If so, it implies that AWTSecurityManager is not our
-        // SecurityManager and we can use a local static variable.
-        // This works around a build time issue.
         if (javaAWTAccess == null) {
             mainAppContextDefault = tz;
         } else {
@@ -822,7 +824,7 @@
     private static final int    GMT_ID_LENGTH = 3;
 
     // a static TimeZone we can reference if no AppContext is in place
-    private static TimeZone mainAppContextDefault;
+    private static volatile TimeZone mainAppContextDefault;
 
     /**
      * Parses a custom time zone identifier and returns a corresponding zone.
--- a/src/share/classes/java/util/jar/Pack200.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/jar/Pack200.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003,2012, 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
@@ -456,12 +456,12 @@
          * The unpacker's progress as a percentage, as periodically
          * updated by the unpacker.
          * Values of 0 - 100 are normal, and -1 indicates a stall.
-         * Observe this property with a {@link PropertyChangeListener}.
+         * Progress can be monitored by polling the value of this
+         * property.
          * <p>
          * At a minimum, the unpacker must set progress to 0
          * at the beginning of a packing operation, and to 100
          * at the end.
-         * @see  #addPropertyChangeListener
          */
         String PROGRESS                 = "pack.progress";
 
@@ -577,7 +577,15 @@
          * @see #properties
          * @see #PROGRESS
          * @param listener  An object to be invoked when a property is changed.
+         * @deprecated The dependency on {@code PropertyChangeListener} creates
+         *             a significant impediment to future modularization of the
+         *             Java platform. This method will be removed in a future
+         *             release.
+         *             Applications that need to monitor progress of the packer
+         *             can poll the value of the {@link #PROGRESS PROGRESS}
+         *             property instead.
          */
+        @Deprecated
         void addPropertyChangeListener(PropertyChangeListener listener) ;
 
         /**
@@ -586,7 +594,12 @@
          *
          * @see #addPropertyChangeListener
          * @param listener  The PropertyChange listener to be removed.
+         * @deprecated The dependency on {@code PropertyChangeListener} creates
+         *             a significant impediment to future modularization of the
+         *             Java platform. This method will be removed in a future
+         *             release.
          */
+        @Deprecated
         void removePropertyChangeListener(PropertyChangeListener listener);
 
     }
@@ -640,12 +653,12 @@
          * The unpacker's progress as a percentage, as periodically
          * updated by the unpacker.
          * Values of 0 - 100 are normal, and -1 indicates a stall.
-         * Observe this property with a {@link PropertyChangeListener}.
+         * Progress can be monitored by polling the value of this
+         * property.
          * <p>
          * At a minimum, the unpacker must set progress to 0
          * at the beginning of a packing operation, and to 100
          * at the end.
-         * @see #addPropertyChangeListener
          */
         String PROGRESS         = "unpack.progress";
 
@@ -708,7 +721,15 @@
          * @see #properties
          * @see #PROGRESS
          * @param listener  An object to be invoked when a property is changed.
+         * @deprecated The dependency on {@code PropertyChangeListener} creates
+         *             a significant impediment to future modularization of the
+         *             Java platform. This method will be removed in a future
+         *             release.
+         *             Applications that need to monitor progress of the
+         *             unpacker can poll the value of the {@link #PROGRESS
+         *             PROGRESS} property instead.
          */
+        @Deprecated
         void addPropertyChangeListener(PropertyChangeListener listener) ;
 
         /**
@@ -717,7 +738,12 @@
          *
          * @see #addPropertyChangeListener
          * @param listener  The PropertyChange listener to be removed.
+         * @deprecated The dependency on {@code PropertyChangeListener} creates
+         *             a significant impediment to future modularization of the
+         *             Java platform. This method will be removed in a future
+         *             release.
          */
+        @Deprecated
         void removePropertyChangeListener(PropertyChangeListener listener);
     }
 
--- a/src/share/classes/java/util/logging/LogManager.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/java/util/logging/LogManager.java	Tue Oct 23 09:41:52 2012 -0700
@@ -311,7 +311,14 @@
      * @exception  SecurityException  if a security manager exists and if
      *             the caller does not have LoggingPermission("control").
      * @exception NullPointerException if the PropertyChangeListener is null.
+     * @deprecated The dependency on {@code PropertyChangeListener} creates a
+     *             significant impediment to future modularization of the Java
+     *             platform. This method will be removed in a future release.
+     *             The global {@code LogManager} can detect changes to the
+     *             logging configuration by overridding the {@link
+     *             #readConfiguration readConfiguration} method.
      */
+    @Deprecated
     public void addPropertyChangeListener(PropertyChangeListener l) throws SecurityException {
         PropertyChangeListener listener = Objects.requireNonNull(l);
         checkAccess();
@@ -336,7 +343,14 @@
      * @param l  event listener (can be null)
      * @exception  SecurityException  if a security manager exists and if
      *             the caller does not have LoggingPermission("control").
+     * @deprecated The dependency on {@code PropertyChangeListener} creates a
+     *             significant impediment to future modularization of the Java
+     *             platform. This method will be removed in a future release.
+     *             The global {@code LogManager} can detect changes to the
+     *             logging configuration by overridding the {@link
+     *             #readConfiguration readConfiguration} method.
      */
+    @Deprecated
     public void removePropertyChangeListener(PropertyChangeListener l) throws SecurityException {
         checkAccess();
         if (l != null) {
--- a/src/share/classes/javax/management/timer/Timer.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/management/timer/Timer.java	Tue Oct 23 09:41:52 2012 -0700
@@ -28,8 +28,7 @@
 import static com.sun.jmx.defaults.JmxProperties.TIMER_LOGGER;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
@@ -128,8 +127,8 @@
      * Table containing all the timer notifications of this timer,
      * with the associated date, period and number of occurrences.
      */
-    private Map<Integer,Object[]> timerTable =
-        new Hashtable<Integer,Object[]>();
+    final private Map<Integer,Object[]> timerTable =
+        new HashMap<>();
 
     /**
      * Past notifications sending on/off flag value.
@@ -163,7 +162,7 @@
      * The notification counter ID.
      * Used to keep the max key value inserted into the timer table.
      */
-    private int counterID = 0;
+    volatile private int counterID = 0;
 
     private java.util.Timer timer;
 
@@ -776,7 +775,7 @@
      *
      * @return The number of timer notifications.
      */
-    public int getNbNotifications() {
+    public synchronized int getNbNotifications() {
         return timerTable.size();
     }
 
@@ -824,7 +823,7 @@
      * @return The timer notification type or null if the identifier is not mapped to any
      * timer notification registered for this timer MBean.
      */
-    public String getNotificationType(Integer id) {
+    public synchronized String getNotificationType(Integer id) {
 
         Object[] obj = timerTable.get(id);
         if (obj != null) {
@@ -841,7 +840,7 @@
      * @return The timer notification detailed message or null if the identifier is not mapped to any
      * timer notification registered for this timer MBean.
      */
-    public String getNotificationMessage(Integer id) {
+    public synchronized String getNotificationMessage(Integer id) {
 
         Object[] obj = timerTable.get(id);
         if (obj != null) {
@@ -862,7 +861,7 @@
     //public Serializable getNotificationUserData(Integer id) {
     // end of NPCTE fix for bugId 4464388
 
-    public Object getNotificationUserData(Integer id) {
+    public synchronized Object getNotificationUserData(Integer id) {
         Object[] obj = timerTable.get(id);
         if (obj != null) {
             return ( ((TimerNotification)obj[TIMER_NOTIF_INDEX]).getUserData() );
@@ -878,7 +877,7 @@
      * @return A copy of the date or null if the identifier is not mapped to any
      * timer notification registered for this timer MBean.
      */
-    public Date getDate(Integer id) {
+    public synchronized Date getDate(Integer id) {
 
         Object[] obj = timerTable.get(id);
         if (obj != null) {
@@ -896,7 +895,7 @@
      * @return A copy of the period or null if the identifier is not mapped to any
      * timer notification registered for this timer MBean.
      */
-    public Long getPeriod(Integer id) {
+    public synchronized Long getPeriod(Integer id) {
 
         Object[] obj = timerTable.get(id);
         if (obj != null) {
@@ -913,7 +912,7 @@
      * @return A copy of the remaining number of occurrences or null if the identifier is not mapped to any
      * timer notification registered for this timer MBean.
      */
-    public Long getNbOccurences(Integer id) {
+    public synchronized Long getNbOccurences(Integer id) {
 
         Object[] obj = timerTable.get(id);
         if (obj != null) {
@@ -931,7 +930,7 @@
      * @return A copy of the flag indicating whether a periodic notification is
      *         executed at <i>fixed-delay</i> or at <i>fixed-rate</i>.
      */
-    public Boolean getFixedRate(Integer id) {
+    public synchronized Boolean getFixedRate(Integer id) {
 
       Object[] obj = timerTable.get(id);
       if (obj != null) {
@@ -982,7 +981,7 @@
      *
      * @return <CODE>true</CODE> if the list of timer notifications is empty, <CODE>false</CODE> otherwise.
      */
-    public boolean isEmpty() {
+    public synchronized boolean isEmpty() {
         return (timerTable.isEmpty());
     }
 
@@ -1184,11 +1183,13 @@
         //
         TimerAlarmClock alarmClock = (TimerAlarmClock)notification.getSource();
 
-        for (Object[] obj : timerTable.values()) {
-            if (obj[ALARM_CLOCK_INDEX] == alarmClock) {
-                timerNotification = (TimerNotification)obj[TIMER_NOTIF_INDEX];
-                timerDate = (Date)obj[TIMER_DATE_INDEX];
-                break;
+        synchronized(Timer.this) {
+            for (Object[] obj : timerTable.values()) {
+                if (obj[ALARM_CLOCK_INDEX] == alarmClock) {
+                    timerNotification = (TimerNotification)obj[TIMER_NOTIF_INDEX];
+                    timerDate = (Date)obj[TIMER_DATE_INDEX];
+                    break;
+                }
             }
         }
 
--- a/src/share/classes/javax/net/ssl/ExtendedSSLSession.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/ExtendedSSLSession.java	Tue Oct 23 09:41:52 2012 -0700
@@ -25,6 +25,8 @@
 
 package javax.net.ssl;
 
+import java.util.List;
+
 /**
  * Extends the <code>SSLSession</code> interface to support additional
  * session attributes.
@@ -83,4 +85,34 @@
      * @see X509ExtendedKeyManager
      */
     public abstract String[] getPeerSupportedSignatureAlgorithms();
+
+    /**
+     * Obtains a {@link List} containing all {@link SNIServerName}s
+     * of the requested Server Name Indication (SNI) extension.
+     * <P>
+     * In server mode, unless the return {@link List} is empty,
+     * the server should use the requested server names to guide its
+     * selection of an appropriate authentication certificate, and/or
+     * other aspects of security policy.
+     * <P>
+     * In client mode, unless the return {@link List} is empty,
+     * the client should use the requested server names to guide its
+     * endpoint identification of the peer's identity, and/or
+     * other aspects of security policy.
+     *
+     * @return a non-null immutable list of {@link SNIServerName}s of the
+     *         requested server name indications. The returned list may be
+     *         empty if no server name indications were requested.
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation
+     *
+     * @see SNIServerName
+     * @see X509ExtendedTrustManager
+     * @see X509ExtendedKeyManager
+     *
+     * @since 1.8
+     */
+    public List<SNIServerName> getRequestedServerNames() {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2003, 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
@@ -186,8 +186,7 @@
             // if the provider does not support it, fallback to peer certs.
             // return the X500Principal of the end-entity cert.
             Certificate[] certs = getPeerCertificates();
-            principal = (X500Principal)
-                ((X509Certificate)certs[0]).getSubjectX500Principal();
+            principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
         }
         return principal;
     }
@@ -216,7 +215,7 @@
             // return the X500Principal of the end-entity cert.
             Certificate[] certs = getLocalCertificates();
             if (certs != null) {
-                principal = (X500Principal)
+                principal =
                         ((X509Certificate)certs[0]).getSubjectX500Principal();
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/javax/net/ssl/SNIHostName.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,394 @@
+/*
+ * 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 javax.net.ssl;
+
+import java.net.IDN;
+import java.nio.ByteBuffer;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharacterCodingException;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Instances of this class represent a server name of type
+ * {@link StandardConstants#SNI_HOST_NAME host_name} in a Server Name
+ * Indication (SNI) extension.
+ * <P>
+ * As described in section 3, "Server Name Indication", of
+ * <A HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>,
+ * "HostName" contains the fully qualified DNS hostname of the server, as
+ * understood by the client.  The encoded server name value of a hostname is
+ * represented as a byte string using ASCII encoding without a trailing dot.
+ * This allows the support of Internationalized Domain Names (IDN) through
+ * the use of A-labels (the ASCII-Compatible Encoding (ACE) form of a valid
+ * string of Internationalized Domain Names for Applications (IDNA)) defined
+ * in <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>.
+ * <P>
+ * Note that {@code SNIHostName} objects are immutable.
+ *
+ * @see SNIServerName
+ * @see StandardConstants#SNI_HOST_NAME
+ *
+ * @since 1.8
+ */
+public final class SNIHostName extends SNIServerName {
+
+    // the decoded string value of the server name
+    private final String hostname;
+
+    /**
+     * Creates an {@code SNIHostName} using the specified hostname.
+     * <P>
+     * Note that per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+     * the encoded server name value of a hostname is
+     * {@link StandardCharsets#US_ASCII}-compliant.  In this method,
+     * {@code hostname} can be a user-friendly Internationalized Domain Name
+     * (IDN).  {@link IDN#toASCII(String, int)} is used to enforce the
+     * restrictions on ASCII characters in hostnames (see
+     * <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
+     * <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
+     * <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>) and
+     * translate the {@code hostname} into ASCII Compatible Encoding (ACE), as:
+     * <pre>
+     *     IDN.toASCII(hostname, IDN.USE_STD3_ASCII_RULES);
+     * </pre>
+     * <P>
+     * The {@code hostname} argument is illegal if it:
+     * <ul>
+     * <li> {@code hostname} is empty,</li>
+     * <li> {@code hostname} ends with a trailing dot,</li>
+     * <li> {@code hostname} is not a valid Internationalized
+     *      Domain Name (IDN) compliant with the RFC 3490 specification.</li>
+     * </ul>
+     * @param  hostname
+     *         the hostname of this server name
+     *
+     * @throws NullPointerException if {@code hostname} is {@code null}
+     * @throws IllegalArgumentException if {@code hostname} is illegal
+     */
+    public SNIHostName(String hostname) {
+        // IllegalArgumentException will be thrown if {@code hostname} is
+        // not a valid IDN.
+        super(StandardConstants.SNI_HOST_NAME,
+                (hostname = IDN.toASCII(
+                    Objects.requireNonNull(hostname,
+                        "Server name value of host_name cannot be null"),
+                    IDN.USE_STD3_ASCII_RULES))
+                .getBytes(StandardCharsets.US_ASCII));
+
+        this.hostname = hostname;
+
+        // check the validity of the string hostname
+        checkHostName();
+    }
+
+    /**
+     * Creates an {@code SNIHostName} using the specified encoded value.
+     * <P>
+     * This method is normally used to parse the encoded name value in a
+     * requested SNI extension.
+     * <P>
+     * Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+     * the encoded name value of a hostname is
+     * {@link StandardCharsets#US_ASCII}-compliant.  However, in the previous
+     * version of the SNI extension (
+     * <A HREF="http://www.ietf.org/rfc/rfc4366.txt">RFC 4366</A>),
+     * the encoded hostname is represented as a byte string using UTF-8
+     * encoding.  For the purpose of version tolerance, this method allows
+     * that the charset of {@code encoded} argument can be
+     * {@link StandardCharsets#UTF_8}, as well as
+     * {@link StandardCharsets#US_ASCII}.  {@link IDN#toASCII(String)} is used
+     * to translate the {@code encoded} argument into ASCII Compatible
+     * Encoding (ACE) hostname.
+     * <P>
+     * It is strongly recommended that this constructor is only used to parse
+     * the encoded name value in a requested SNI extension.  Otherwise, to
+     * comply with <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+     * please always use {@link StandardCharsets#US_ASCII}-compliant charset
+     * and enforce the restrictions on ASCII characters in hostnames (see
+     * <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
+     * <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
+     * <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>)
+     * for {@code encoded} argument, or use {@link SNIHostName(String)} instead.
+     * <P>
+     * The {@code encoded} argument is illegal if it:
+     * <ul>
+     * <li> {@code encoded} is empty,</li>
+     * <li> {@code encoded} ends with a trailing dot,</li>
+     * <li> {@code encoded} is not encoded in
+     *      {@link StandardCharsets#US_ASCII} or
+     *      {@link StandardCharsets#UTF_8}-compliant charset,</li>
+     * <li> {@code encoded} is not a valid Internationalized
+     *      Domain Name (IDN) compliant with the RFC 3490 specification.</li>
+     * </ul>
+     *
+     * <P>
+     * Note that the {@code encoded} byte array is cloned
+     * to protect against subsequent modification.
+     *
+     * @param  encoded
+     *         the encoded hostname of this server name
+     *
+     * @throws NullPointerException if {@code encoded} is {@code null}
+     * @throws IllegalArgumentException if {@code encoded} is illegal
+     */
+    public SNIHostName(byte[] encoded) {
+        // NullPointerException will be thrown if {@code encoded} is null
+        super(StandardConstants.SNI_HOST_NAME, encoded);
+
+        // Compliance: RFC 4366 requires that the hostname is represented
+        // as a byte string using UTF_8 encoding [UTF8]
+        try {
+            // Please don't use {@link String} constructors because they
+            // do not report coding errors.
+            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
+                    .onMalformedInput(CodingErrorAction.REPORT)
+                    .onUnmappableCharacter(CodingErrorAction.REPORT);
+
+            this.hostname = IDN.toASCII(
+                    decoder.decode(ByteBuffer.wrap(encoded)).toString());
+        } catch (RuntimeException | CharacterCodingException e) {
+            throw new IllegalArgumentException(
+                        "The encoded server name value is invalid", e);
+        }
+
+        // check the validity of the string hostname
+        checkHostName();
+    }
+
+    /**
+     * Returns the {@link StandardCharsets#US_ASCII}-compliant hostname of
+     * this {@code SNIHostName} object.
+     * <P>
+     * Note that, per
+     * <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, the
+     * returned hostname may be an internationalized domain name that
+     * contains A-labels. See
+     * <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>
+     * for more information about the detailed A-label specification.
+     *
+     * @return the {@link StandardCharsets#US_ASCII}-compliant hostname
+     *         of this {@code SNIHostName} object
+     */
+    public String getAsciiName() {
+        return hostname;
+    }
+
+    /**
+     * Compares this server name to the specified object.
+     * <P>
+     * Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, DNS
+     * hostnames are case-insensitive.  Two server hostnames are equal if,
+     * and only if, they have the same name type, and the hostnames are
+     * equal in a case-independent comparison.
+     *
+     * @param  other
+     *         the other server name object to compare with.
+     * @return true if, and only if, the {@code other} is considered
+     *         equal to this instance
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (other instanceof SNIHostName) {
+            return hostname.equalsIgnoreCase(((SNIHostName)other).hostname);
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for this {@code SNIHostName}.
+     * <P>
+     * The hash code value is generated using the case-insensitive hostname
+     * of this {@code SNIHostName}.
+     *
+     * @return a hash code value for this {@code SNIHostName}.
+     */
+    @Override
+    public int hashCode() {
+        int result = 17;        // 17/31: prime number to decrease collisions
+        result = 31 * result + hostname.toUpperCase(Locale.ENGLISH).hashCode();
+
+        return result;
+    }
+
+    /**
+     * Returns a string representation of the object, including the DNS
+     * hostname in this {@code SNIHostName} object.
+     * <P>
+     * The exact details of the representation are unspecified and subject
+     * to change, but the following may be regarded as typical:
+     * <pre>
+     *     "type=host_name (0), value={@literal <hostname>}"
+     * </pre>
+     * The "{@literal <hostname>}" is an ASCII representation of the hostname,
+     * which may contains A-labels.  For example, a returned value of an pseudo
+     * hostname may look like:
+     * <pre>
+     *     "type=host_name (0), value=www.example.com"
+     * </pre>
+     * or
+     * <pre>
+     *     "type=host_name (0), value=xn--fsqu00a.xn--0zwm56d"
+     * </pre>
+     * <P>
+     * Please NOTE that the exact details of the representation are unspecified
+     * and subject to change.
+     *
+     * @return a string representation of the object.
+     */
+    @Override
+    public String toString() {
+        return "type=host_name (0), value=" + hostname;
+    }
+
+    /**
+     * Creates an {@link SNIMatcher} object for {@code SNIHostName}s.
+     * <P>
+     * This method can be used by a server to verify the acceptable
+     * {@code SNIHostName}s.  For example,
+     * <pre>
+     *     SNIMatcher matcher =
+     *         SNIHostName.createSNIMatcher("www\\.example\\.com");
+     * </pre>
+     * will accept the hostname "www.example.com".
+     * <pre>
+     *     SNIMatcher matcher =
+     *         SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");
+     * </pre>
+     * will accept hostnames "www.example.com" and "www.example.org".
+     *
+     * @param  regex
+     *         the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
+     *         regular expression pattern</a>
+     *         representing the hostname(s) to match
+     * @throws NullPointerException if {@code regex} is
+     *         {@code null}
+     * @throws PatternSyntaxException if the regular expression's syntax
+     *         is invalid
+     */
+    public static SNIMatcher createSNIMatcher(String regex) {
+        if (regex == null) {
+            throw new NullPointerException(
+                "The regular expression cannot be null");
+        }
+
+        return new SNIHostNameMatcher(regex);
+    }
+
+    // check the validity of the string hostname
+    private void checkHostName() {
+        if (hostname.isEmpty()) {
+            throw new IllegalArgumentException(
+                "Server name value of host_name cannot be empty");
+        }
+
+        if (hostname.endsWith(".")) {
+            throw new IllegalArgumentException(
+                "Server name value of host_name cannot have the trailing dot");
+        }
+    }
+
+    private final static class SNIHostNameMatcher extends SNIMatcher {
+
+        // the compiled representation of a regular expression.
+        private final Pattern pattern;
+
+        /**
+         * Creates an SNIHostNameMatcher object.
+         *
+         * @param  regex
+         *         the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
+         *         regular expression pattern</a>
+         *         representing the hostname(s) to match
+         * @throws NullPointerException if {@code regex} is
+         *         {@code null}
+         * @throws PatternSyntaxException if the regular expression's syntax
+         *         is invalid
+         */
+        SNIHostNameMatcher(String regex) {
+            super(StandardConstants.SNI_HOST_NAME);
+            pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+        }
+
+        /**
+         * Attempts to match the given {@link SNIServerName}.
+         *
+         * @param  serverName
+         *         the {@link SNIServerName} instance on which this matcher
+         *         performs match operations
+         *
+         * @return {@code true} if, and only if, the matcher matches the
+         *         given {@code serverName}
+         *
+         * @throws NullPointerException if {@code serverName} is {@code null}
+         * @throws IllegalArgumentException if {@code serverName} is
+         *         not of {@code StandardConstants#SNI_HOST_NAME} type
+         *
+         * @see SNIServerName
+         */
+        @Override
+        public boolean matches(SNIServerName serverName) {
+            if (serverName == null) {
+                throw new NullPointerException(
+                    "The SNIServerName argument cannot be null");
+            }
+
+            SNIHostName hostname;
+            if (!(serverName instanceof SNIHostName)) {
+                if (serverName.getType() != StandardConstants.SNI_HOST_NAME) {
+                    throw new IllegalArgumentException(
+                        "The server name type is not host_name");
+                }
+
+                try {
+                    hostname = new SNIHostName(serverName.getEncoded());
+                } catch (NullPointerException | IllegalArgumentException e) {
+                    return false;
+                }
+            } else {
+                hostname = (SNIHostName)serverName;
+            }
+
+            // Let's first try the ascii name matching
+            String asciiName = hostname.getAsciiName();
+            if (pattern.matcher(asciiName).matches()) {
+                return true;
+            }
+
+            // May be an internationalized domain name, check the Unicode
+            // representations.
+            return pattern.matcher(IDN.toUnicode(asciiName)).matches();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/javax/net/ssl/SNIMatcher.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,105 @@
+/*
+ * 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 javax.net.ssl;
+
+/**
+ * Instances of this class represent a matcher that performs match
+ * operations on an {@link SNIServerName} instance.
+ * <P>
+ * Servers can use Server Name Indication (SNI) information to decide if
+ * specific {@link SSLSocket} or {@link SSLEngine} instances should accept
+ * a connection.  For example, when multiple "virtual" or "name-based"
+ * servers are hosted on a single underlying network address, the server
+ * application can use SNI information to determine whether this server is
+ * the exact server that the client wants to access.  Instances of this
+ * class can be used by a server to verify the acceptable server names of
+ * a particular type, such as host names.
+ * <P>
+ * {@code SNIMatcher} objects are immutable.  Subclasses should not provide
+ * methods that can change the state of an instance once it has been created.
+ *
+ * @see SNIServerName
+ * @see SNIHostName
+ * @see SSLParameters#getSNIMatchers()
+ * @see SSLParameters#setSNIMatchers(Collection<SNIMatcher>)
+ *
+ * @since 1.8
+ */
+public abstract class SNIMatcher {
+
+    // the type of the server name that this matcher performs on
+    private final int type;
+
+    /**
+     * Creates an {@code SNIMatcher} using the specified server name type.
+     *
+     * @param  type
+     *         the type of the server name that this matcher performs on
+     *
+     * @throws IllegalArgumentException if {@code type} is not in the range
+     *         of 0 to 255, inclusive.
+     */
+    protected SNIMatcher(int type) {
+        if (type < 0) {
+            throw new IllegalArgumentException(
+                "Server name type cannot be less than zero");
+        } else if (type > 255) {
+            throw new IllegalArgumentException(
+                "Server name type cannot be greater than 255");
+        }
+
+        this.type = type;
+    }
+
+    /**
+     * Returns the server name type of this {@code SNIMatcher} object.
+     *
+     * @return the server name type of this {@code SNIMatcher} object.
+     *
+     * @see SNIServerName
+     */
+    public final int getType() {
+        return type;
+    }
+
+    /**
+     * Attempts to match the given {@link SNIServerName}.
+     *
+     * @param  serverName
+     *         the {@link SNIServerName} instance on which this matcher
+     *         performs match operations
+     *
+     * @return {@code true} if, and only if, the matcher matches the
+     *         given {@code serverName}
+     *
+     * @throws NullPointerException if {@code serverName} is {@code null}
+     * @throws IllegalArgumentException if {@code serverName} is
+     *         not of the given server name type of this matcher
+     *
+     * @see SNIServerName
+     */
+    public abstract boolean matches(SNIServerName serverName);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/javax/net/ssl/SNIServerName.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,213 @@
+/*
+ * 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 javax.net.ssl;
+
+import java.util.Arrays;
+
+/**
+ * Instances of this class represent a server name in a Server Name
+ * Indication (SNI) extension.
+ * <P>
+ * The SNI extension is a feature that extends the SSL/TLS protocols to
+ * indicate what server name the client is attempting to connect to during
+ * handshaking.  See section 3, "Server Name Indication", of <A
+ * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
+ * <P>
+ * {@code SNIServerName} objects are immutable.  Subclasses should not provide
+ * methods that can change the state of an instance once it has been created.
+ *
+ * @see SSLParameters#getServerNames()
+ * @see SSLParameters#setServerNames(List<SNIServerName>)
+ *
+ * @since 1.8
+ */
+public abstract class SNIServerName {
+
+    // the type of the server name
+    private final int type;
+
+    // the encoded value of the server name
+    private final byte[] encoded;
+
+    // the hex digitals
+    private static final char[] HEXES = "0123456789ABCDEF".toCharArray();
+
+    /**
+     * Creates an {@code SNIServerName} using the specified name type and
+     * encoded value.
+     * <P>
+     * Note that the {@code encoded} byte array is cloned to protect against
+     * subsequent modification.
+     *
+     * @param  type
+     *         the type of the server name
+     * @param  encoded
+     *         the encoded value of the server name
+     *
+     * @throws IllegalArgumentException if {@code type} is not in the range
+     *         of 0 to 255, inclusive.
+     * @throws NullPointerException if {@code encoded} is null
+     */
+    protected SNIServerName(int type, byte[] encoded) {
+        if (type < 0) {
+            throw new IllegalArgumentException(
+                "Server name type cannot be less than zero");
+        } else if (type > 255) {
+            throw new IllegalArgumentException(
+                "Server name type cannot be greater than 255");
+        }
+        this.type = type;
+
+        if (encoded == null) {
+            throw new NullPointerException(
+                "Server name encoded value cannot be null");
+        }
+        this.encoded = encoded.clone();
+    }
+
+
+    /**
+     * Returns the name type of this server name.
+     *
+     * @return the name type of this server name
+     */
+    public final int getType() {
+        return type;
+    }
+
+    /**
+     * Returns a copy of the encoded server name value of this server name.
+     *
+     * @return a copy of the encoded server name value of this server name
+     */
+    public final byte[] getEncoded() {
+        return encoded.clone();
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this server name.
+     *
+     * @return true if, and only if, {@code other} is of the same class
+     *         of this object, and has the same name type and
+     *         encoded value as this server name.
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (this.getClass() != other.getClass()) {
+            return false;
+        }
+
+        SNIServerName that = (SNIServerName)other;
+        return (this.type == that.type) &&
+                    Arrays.equals(this.encoded, that.encoded);
+    }
+
+    /**
+     * Returns a hash code value for this server name.
+     * <P>
+     * The hash code value is generated using the name type and encoded
+     * value of this server name.
+     *
+     * @return a hash code value for this server name.
+     */
+    @Override
+    public int hashCode() {
+        int result = 17;    // 17/31: prime number to decrease collisions
+        result = 31 * result + type;
+        result = 31 * result + Arrays.hashCode(encoded);
+
+        return result;
+    }
+
+    /**
+     * Returns a string representation of this server name, including the server
+     * name type and the encoded server name value in this
+     * {@code SNIServerName} object.
+     * <P>
+     * The exact details of the representation are unspecified and subject
+     * to change, but the following may be regarded as typical:
+     * <pre>
+     *     "type={@literal <name type>}, value={@literal <name value>}"
+     * </pre>
+     * <P>
+     * In this class, the format of "{@literal <name type>}" is
+     * "[LITERAL] (INTEGER)", where the optional "LITERAL" is the literal
+     * name, and INTEGER is the integer value of the name type.  The format
+     * of "{@literal <name value>}" is "XX:...:XX", where "XX" is the
+     * hexadecimal digit representation of a byte value. For example, a
+     * returned value of an pseudo server name may look like:
+     * <pre>
+     *     "type=(31), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
+     * </pre>
+     * or
+     * <pre>
+     *     "type=host_name (0), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
+     * </pre>
+     *
+     * <P>
+     * Please NOTE that the exact details of the representation are unspecified
+     * and subject to change, and subclasses may override the method with
+     * their own formats.
+     *
+     * @return a string representation of this server name
+     */
+    @Override
+    public String toString() {
+        if (type == StandardConstants.SNI_HOST_NAME) {
+            return "type=host_name (0), value=" + toHexString(encoded);
+        } else {
+            return "type=(" + type + "), value=" + toHexString(encoded);
+        }
+    }
+
+    // convert byte array to hex string
+    private static String toHexString(byte[] bytes) {
+        if (bytes.length == 0) {
+            return "(empty)";
+        }
+
+        StringBuilder sb = new StringBuilder(bytes.length * 3 - 1);
+        boolean isInitial = true;
+        for (byte b : bytes) {
+            if (isInitial) {
+                isInitial = false;
+            } else {
+                sb.append(':');
+            }
+
+            int k = b & 0xFF;
+            sb.append(HEXES[k >>> 4]);
+            sb.append(HEXES[k & 0xF]);
+        }
+
+        return sb.toString();
+    }
+}
+
--- a/src/share/classes/javax/net/ssl/SSLEngine.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/SSLEngine.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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
@@ -1214,15 +1214,19 @@
      *
      * <p>This means:
      * <ul>
-     * <li>if <code>params.getCipherSuites()</code> is non-null,
-     *   <code>setEnabledCipherSuites()</code> is called with that value
-     * <li>if <code>params.getProtocols()</code> is non-null,
-     *   <code>setEnabledProtocols()</code> is called with that value
-     * <li>if <code>params.getNeedClientAuth()</code> or
-     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
-     *   <code>setNeedClientAuth(true)</code> and
-     *   <code>setWantClientAuth(true)</code> are called, respectively;
-     *   otherwise <code>setWantClientAuth(false)</code> is called.
+     * <li>If {@code params.getCipherSuites()} is non-null,
+     *   {@code setEnabledCipherSuites()} is called with that value.</li>
+     * <li>If {@code params.getProtocols()} is non-null,
+     *   {@code setEnabledProtocols()} is called with that value.</li>
+     * <li>If {@code params.getNeedClientAuth()} or
+     *   {@code params.getWantClientAuth()} return {@code true},
+     *   {@code setNeedClientAuth(true)} and
+     *   {@code setWantClientAuth(true)} are called, respectively;
+     *   otherwise {@code setWantClientAuth(false)} is called.</li>
+     * <li>If {@code params.getServerNames()} is non-null, the engine will
+     *   configure its server names with that value.</li>
+     * <li>If {@code params.getSNIMatchers()} is non-null, the engine will
+     *   configure its SNI matchers with that value.</li>
      * </ul>
      *
      * @param params the parameters
--- a/src/share/classes/javax/net/ssl/SSLParameters.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/SSLParameters.java	Tue Oct 23 09:41:52 2012 -0700
@@ -26,13 +26,23 @@
 package javax.net.ssl;
 
 import java.security.AlgorithmConstraints;
+import java.util.Map;
+import java.util.List;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.regex.Pattern;
 
 /**
  * Encapsulates parameters for an SSL/TLS connection. The parameters
  * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
  * the list of protocols to be allowed, the endpoint identification
- * algorithm during SSL/TLS handshaking, the algorithm constraints and
- * whether SSL/TLS servers should request or require client authentication.
+ * algorithm during SSL/TLS handshaking, the Server Name Indication (SNI),
+ * the algorithm constraints and whether SSL/TLS servers should request
+ * or require client authentication.
  * <p>
  * SSLParameters can be created via the constructors in this class.
  * Objects can also be obtained using the <code>getSSLParameters()</code>
@@ -47,7 +57,7 @@
  * SSLParameters can be applied to a connection via the methods
  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
  * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
- * and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
+ * and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.
  *
  * @see SSLSocket
  * @see SSLEngine
@@ -63,11 +73,15 @@
     private boolean needClientAuth;
     private String identificationAlgorithm;
     private AlgorithmConstraints algorithmConstraints;
+    private Map<Integer, SNIServerName> sniNames = null;
+    private Map<Integer, SNIMatcher> sniMatchers = null;
 
     /**
      * Constructs SSLParameters.
      * <p>
-     * The cipherSuites and protocols values are set to <code>null</code>,
+     * The values of cipherSuites, protocols, cryptographic algorithm
+     * constraints, endpoint identification algorithm, server names and
+     * server name matchers are set to <code>null</code>,
      * wantClientAuth and needClientAuth are set to <code>false</code>.
      */
     public SSLParameters() {
@@ -254,4 +268,173 @@
         this.identificationAlgorithm = algorithm;
     }
 
+    /**
+     * Sets the desired {@link SNIServerName}s of the Server Name
+     * Indication (SNI) parameter.
+     * <P>
+     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+     * operating in client mode.
+     * <P>
+     * Note that the {@code serverNames} list is cloned
+     * to protect against subsequent modification.
+     *
+     * @param  serverNames
+     *         the list of desired {@link SNIServerName}s (or null)
+     *
+     * @throws NullPointerException if the {@code serverNames}
+     *         contains {@code null} element
+     * @throws IllegalArgumentException if the {@code serverNames}
+     *         contains more than one name of the same name type
+     *
+     * @see SNIServerName
+     * @see #getServerNames()
+     *
+     * @since 1.8
+     */
+    public final void setServerNames(List<SNIServerName> serverNames) {
+        if (serverNames != null) {
+            if (!serverNames.isEmpty()) {
+                sniNames = new LinkedHashMap<>(serverNames.size());
+                for (SNIServerName serverName : serverNames) {
+                    if (sniNames.put(serverName.getType(),
+                                                serverName) != null) {
+                        throw new IllegalArgumentException(
+                                    "Duplicated server name of type " +
+                                    serverName.getType());
+                    }
+                }
+            } else {
+                sniNames = Collections.<Integer, SNIServerName>emptyMap();
+            }
+        } else {
+            sniNames = null;
+        }
+    }
+
+    /**
+     * Returns a {@link List} containing all {@link SNIServerName}s of the
+     * Server Name Indication (SNI) parameter, or null if none has been set.
+     * <P>
+     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+     * operating in client mode.
+     * <P>
+     * For SSL/TLS connections, the underlying SSL/TLS provider
+     * may specify a default value for a certain server name type.  In
+     * client mode, it is recommended that, by default, providers should
+     * include the server name indication whenever the server can be located
+     * by a supported server name type.
+     * <P>
+     * It is recommended that providers initialize default Server Name
+     * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
+     * In the following examples, the server name could be represented by an
+     * instance of {@link SNIHostName} which has been initialized with the
+     * hostname "www.example.com" and type
+     * {@link StandardConstants#SNI_HOST_NAME}.
+     *
+     * <pre>
+     *     Socket socket =
+     *         sslSocketFactory.createSocket("www.example.com", 443);
+     * </pre>
+     * or
+     * <pre>
+     *     SSLEngine engine =
+     *         sslContext.createSSLEngine("www.example.com", 443);
+     * </pre>
+     * <P>
+     *
+     * @return null or an immutable list of non-null {@link SNIServerName}s
+     *
+     * @see List
+     * @see #setServerNames(List<SNIServerName>)
+     *
+     * @since 1.8
+     */
+    public final List<SNIServerName> getServerNames() {
+        if (sniNames != null) {
+            if (!sniNames.isEmpty()) {
+                return Collections.<SNIServerName>unmodifiableList(
+                                        new ArrayList<>(sniNames.values()));
+            } else {
+                return Collections.<SNIServerName>emptyList();
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
+     * parameter.
+     * <P>
+     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+     * operating in server mode.
+     * <P>
+     * Note that the {@code matchers} collection is cloned to protect
+     * against subsequent modification.
+     *
+     * @param  matchers
+     *         the collection of {@link SNIMatcher}s (or null)
+     *
+     * @throws NullPointerException if the {@code matchers}
+     *         contains {@code null} element
+     * @throws IllegalArgumentException if the {@code matchers}
+     *         contains more than one name of the same name type
+     *
+     * @see Collection
+     * @see SNIMatcher
+     * @see #getSNIMatchers()
+     *
+     * @since 1.8
+     */
+    public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
+        if (matchers != null) {
+            if (!matchers.isEmpty()) {
+                sniMatchers = new HashMap<>(matchers.size());
+                for (SNIMatcher matcher : matchers) {
+                    if (sniMatchers.put(matcher.getType(),
+                                                matcher) != null) {
+                        throw new IllegalArgumentException(
+                                    "Duplicated server name of type " +
+                                    matcher.getType());
+                    }
+                }
+            } else {
+                sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
+            }
+        } else {
+            sniMatchers = null;
+        }
+    }
+
+    /**
+     * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
+     * Server Name Indication (SNI) parameter, or null if none has been set.
+     * <P>
+     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+     * operating in server mode.
+     * <P>
+     * For better interoperability, providers generally will not define
+     * default matchers so that by default servers will ignore the SNI
+     * extension and continue the handshake.
+     *
+     * @return null or an immutable collection of non-null {@link SNIMatcher}s
+     *
+     * @see SNIMatcher
+     * @see #setSNIMatchers(Collection<SNIMatcher>)
+     *
+     * @since 1.8
+     */
+    public final Collection<SNIMatcher> getSNIMatchers() {
+        if (sniMatchers != null) {
+            if (!sniMatchers.isEmpty()) {
+                return Collections.<SNIMatcher>unmodifiableList(
+                                        new ArrayList<>(sniMatchers.values()));
+            } else {
+                return Collections.<SNIMatcher>emptyList();
+            }
+        }
+
+        return null;
+    }
 }
+
--- a/src/share/classes/javax/net/ssl/SSLServerSocket.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/SSLServerSocket.java	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -484,15 +484,19 @@
      *
      * <p>This means:
      * <ul>
-     * <li>if <code>params.getCipherSuites()</code> is non-null,
-     *   <code>setEnabledCipherSuites()</code> is called with that value
-     * <li>if <code>params.getProtocols()</code> is non-null,
-     *   <code>setEnabledProtocols()</code> is called with that value
-     * <li>if <code>params.getNeedClientAuth()</code> or
-     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
-     *   <code>setNeedClientAuth(true)</code> and
-     *   <code>setWantClientAuth(true)</code> are called, respectively;
-     *   otherwise <code>setWantClientAuth(false)</code> is called.
+     * <li>If {@code params.getCipherSuites()} is non-null,
+     *   {@code setEnabledCipherSuites()} is called with that value.</li>
+     * <li>If {@code params.getProtocols()} is non-null,
+     *   {@code setEnabledProtocols()} is called with that value.</li>
+     * <li>If {@code params.getNeedClientAuth()} or
+     *   {@code params.getWantClientAuth()} return {@code true},
+     *   {@code setNeedClientAuth(true)} and
+     *   {@code setWantClientAuth(true)} are called, respectively;
+     *   otherwise {@code setWantClientAuth(false)} is called.</li>
+     * <li>If {@code params.getServerNames()} is non-null, the socket will
+     *   configure its server names with that value.</li>
+     * <li>If {@code params.getSNIMatchers()} is non-null, the socket will
+     *   configure its SNI matchers with that value.</li>
      * </ul>
      *
      * @param params the parameters
--- a/src/share/classes/javax/net/ssl/SSLSocket.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/SSLSocket.java	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -626,15 +626,19 @@
      *
      * <p>This means:
      * <ul>
-     * <li>if <code>params.getCipherSuites()</code> is non-null,
-     *   <code>setEnabledCipherSuites()</code> is called with that value
-     * <li>if <code>params.getProtocols()</code> is non-null,
-     *   <code>setEnabledProtocols()</code> is called with that value
-     * <li>if <code>params.getNeedClientAuth()</code> or
-     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
-     *   <code>setNeedClientAuth(true)</code> and
-     *   <code>setWantClientAuth(true)</code> are called, respectively;
-     *   otherwise <code>setWantClientAuth(false)</code> is called.
+     * <li>If {@code params.getCipherSuites()} is non-null,
+     *   {@code setEnabledCipherSuites()} is called with that value.</li>
+     * <li>If {@code params.getProtocols()} is non-null,
+     *   {@code setEnabledProtocols()} is called with that value.</li>
+     * <li>If {@code params.getNeedClientAuth()} or
+     *   {@code params.getWantClientAuth()} return {@code true},
+     *   {@code setNeedClientAuth(true)} and
+     *   {@code setWantClientAuth(true)} are called, respectively;
+     *   otherwise {@code setWantClientAuth(false)} is called.</li>
+     * <li>If {@code params.getServerNames()} is non-null, the socket will
+     *   configure its server names with that value.</li>
+     * <li>If {@code params.getSNIMatchers()} is non-null, the socket will
+     *   configure its SNI matchers with that value.</li>
      * </ul>
      *
      * @param params the parameters
--- a/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/net/ssl/SSLSocketFactory.java	Tue Oct 23 09:41:52 2012 -0700
@@ -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
@@ -29,6 +29,7 @@
 import java.net.*;
 import javax.net.SocketFactory;
 import java.io.IOException;
+import java.io.InputStream;
 import java.security.*;
 import java.util.Locale;
 
@@ -180,8 +181,55 @@
      * @throws NullPointerException if the parameter s is null
      */
     public abstract Socket createSocket(Socket s, String host,
-                                        int port, boolean autoClose)
-    throws IOException;
+            int port, boolean autoClose) throws IOException;
+
+    /**
+     * Creates a server mode {@link Socket} layered over an
+     * existing connected socket, and is able to read data which has
+     * already been consumed/removed from the {@link Socket}'s
+     * underlying {@link InputStream}.
+     * <p>
+     * This method can be used by a server application that needs to
+     * observe the inbound data but still create valid SSL/TLS
+     * connections: for example, inspection of Server Name Indication
+     * (SNI) extensions (See section 3 of <A
+     * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions
+     * (RFC6066)</A>).  Data that has been already removed from the
+     * underlying {@link InputStream} should be loaded into the
+     * {@code consumed} stream before this method is called, perhaps
+     * using a {@link ByteArrayInputStream}.  When this {@link Socket}
+     * begins handshaking, it will read all of the data in
+     * {@code consumed} until it reaches {@code EOF}, then all further
+     * data is read from the underlying {@link InputStream} as
+     * usual.
+     * <p>
+     * The returned socket is configured using the socket options
+     * established for this factory, and is set to use server mode when
+     * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}).
+     *
+     * @param  s
+     *         the existing socket
+     * @param  consumed
+     *         the consumed inbound network data that has already been
+     *         removed from the existing {@link Socket}
+     *         {@link InputStream}.  This parameter may be
+     *         {@code null} if no data has been removed.
+     * @param  autoClose close the underlying socket when this socket is closed.
+     *
+     * @return the {@link Socket} compliant with the socket options
+     *         established for this factory
+     *
+     * @throws IOException if an I/O error occurs when creating the socket
+     * @throws UnsupportedOperationException if the underlying provider
+     *         does not implement the operation
+     * @throws NullPointerException if {@code s} is {@code null}
+     *
+     * @since 1.8
+     */
+    public Socket createSocket(Socket s, InputStream consumed,
+            boolean autoClose) throws IOException {
+        throw new UnsupportedOperationException();
+    }
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/javax/net/ssl/StandardConstants.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,56 @@
+/*
+ * 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 javax.net.ssl;
+
+/**
+ * Standard constants definitions
+ *
+ * @since 1.8
+ */
+public final class StandardConstants {
+
+    // Suppress default constructor for noninstantiability
+    private StandardConstants() {
+        throw new AssertionError(
+            "No javax.net.ssl.StandardConstants instances for you!");
+    }
+
+    /**
+     * The "host_name" type representing of a DNS hostname
+     * (see {@link SNIHostName}) in a Server Name Indication (SNI) extension.
+     * <P>
+     * The SNI extension is a feature that extends the SSL/TLS protocols to
+     * indicate what server name the client is attempting to connect to during
+     * handshaking.  See section 3, "Server Name Indication", of <A
+     * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
+     * <P>
+     * The value of this constant is {@value}.
+     *
+     * @see SNIServerName
+     * @see SNIHostName
+     */
+    public static final int SNI_HOST_NAME = 0x00;
+}
--- a/src/share/classes/javax/sql/rowset/BaseRowSet.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/sql/rowset/BaseRowSet.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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
@@ -1850,7 +1850,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setFloat");
         }
-        params.put(Integer.valueOf(parameterIndex - 1), new Float(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Float.valueOf(x));
     }
 
     /**
@@ -1882,7 +1882,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setDouble");
         }
-        params.put(Integer.valueOf(parameterIndex - 1), new Double(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Double.valueOf(x));
     }
 
     /**
@@ -2389,7 +2389,7 @@
      * @deprecated getCharacterStream should be used in its place
      * @see #getParams
      */
-
+    @Deprecated
     public void setUnicodeStream(int parameterIndex, java.io.InputStream x, int length) throws SQLException {
         Object unicodeStream[];
         checkParamIndex(parameterIndex);
--- a/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java	Tue Oct 23 09:41:52 2012 -0700
@@ -215,7 +215,7 @@
      */
     @SuppressWarnings("unchecked")
     public void writeFloat(float x) throws SQLException {
-        attribs.add(new Float(x));
+        attribs.add(Float.valueOf(x));
     }
 
     /**
@@ -230,7 +230,7 @@
      */
     @SuppressWarnings("unchecked")
     public void writeDouble(double x) throws SQLException{
-        attribs.add(new Double(x));
+        attribs.add(Double.valueOf(x));
     }
 
     /**
--- a/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Tue Oct 23 09:40:06 2012 -0700
+++ b/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Tue Oct 23 09:41:52 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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
@@ -229,11 +229,7 @@
      * The standard resource file name.
      */
     private static String ROWSET_PROPERTIES = "rowset.properties";
-    /**
-     * The RI Optimistic Provider.
-     */
-    private static String default_provider =
-            "com.sun.rowset.providers.RIOptimisticProvider";
+
     /**
      *  Permission required to invoke setJNDIContext and setLogger
      */
@@ -248,24 +244,13 @@
      * The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
      */
     private static volatile Logger rsLogger;
-    /**
-     *
-     */
-    private static Level rsLevel;
+
     /**
      * The registry of available <code>SyncProvider</code> implementations.
      * See section 2.0 of the class comment for <code>SyncFactory</code> for an
      * explanation of how a provider can be added to this registry.
      */
     private static Hashtable<String, SyncProvider> implementations;
-    /**
-     * Internal sync object used to maintain the SPI as a singleton
-     */
-    private static Object logSync = new Object();
-    /**
-     * Internal PrintWriter field for logging facility
-     */
-    private static java.io.PrintWriter logWriter = null;
 
     /**
      * Adds the the given synchronization provider to the factory register. Guidelines
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,186 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java annotation. The methods of this class must be
+ * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
+ * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public abstract class AnnotationVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The annotation visitor to which this visitor must delegate method calls.
+     * May be null.
+     */
+    protected AnnotationVisitor av;
+
+    /**
+     * Constructs a new {@link AnnotationVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public AnnotationVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link AnnotationVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param av the annotation visitor to which this visitor must delegate
+     *        method calls. May be null.
+     */
+    public AnnotationVisitor(final int api, final AnnotationVisitor av) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.av = av;
+    }
+
+    /**
+     * Visits a primitive value of the annotation.
+     *
+     * @param name the value name.
+     * @param value the actual value, whose type must be {@link Byte},
+     *        {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
+     *        , {@link Long}, {@link Float}, {@link Double}, {@link String} or
+     *        {@link Type} or OBJECT or ARRAY sort. This value can also be an
+     *        array of byte, boolean, short, char, int, long, float or double
+     *        values (this is equivalent to using {@link #visitArray visitArray}
+     *        and visiting each array element in turn, but is more convenient).
+     */
+    public void visit(String name, Object value) {
+        if (av != null) {
+            av.visit(name, value);
+        }
+    }
+
+    /**
+     * Visits an enumeration value of the annotation.
+     *
+     * @param name the value name.
+     * @param desc the class descriptor of the enumeration class.
+     * @param value the actual enumeration value.
+     */
+    public void visitEnum(String name, String desc, String value) {
+        if (av != null) {
+            av.visitEnum(name, desc, value);
+        }
+    }
+
+    /**
+     * Visits a nested annotation value of the annotation.
+     *
+     * @param name the value name.
+     * @param desc the class descriptor of the nested annotation class.
+     * @return a visitor to visit the actual nested annotation value, or
+     *         <tt>null</tt> if this visitor is not interested in visiting
+     *         this nested annotation. <i>The nested annotation value must be
+     *         fully visited before calling other methods on this annotation
+     *         visitor</i>.
+     */
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        if (av != null) {
+            return av.visitAnnotation(name, desc);
+        }
+        return null;
+    }
+
+    /**
+     * Visits an array value of the annotation. Note that arrays of primitive
+     * types (such as byte, boolean, short, char, int, long, float or double)
+     * can be passed as value to {@link #visit visit}. This is what
+     * {@link ClassReader} does.
+     *
+     * @param name the value name.
+     * @return a visitor to visit the actual array value elements, or
+     *         <tt>null</tt> if this visitor is not interested in visiting
+     *         these values. The 'name' parameters passed to the methods of this
+     *         visitor are ignored. <i>All the array values must be visited
+     *         before calling other methods on this annotation visitor</i>.
+     */
+    public AnnotationVisitor visitArray(String name) {
+        if (av != null) {
+            return av.visitArray(name);
+        }
+        return null;
+    }
+
+    /**
+     * Visits the end of the annotation.
+     */
+    public void visitEnd() {
+        if (av != null) {
+            av.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,351 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+final class AnnotationWriter extends AnnotationVisitor {
+
+    /**
+     * The class writer to which this annotation must be added.
+     */
+    private final ClassWriter cw;
+
+    /**
+     * The number of values in this annotation.
+     */
+    private int size;
+
+    /**
+     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
+     * writers used for annotation default and annotation arrays use unnamed
+     * values.
+     */
+    private final boolean named;
+
+    /**
+     * The annotation values in bytecode form. This byte vector only contains
+     * the values themselves, i.e. the number of values must be stored as a
+     * unsigned short just before these bytes.
+     */
+    private final ByteVector bv;
+
+    /**
+     * The byte vector to be used to store the number of values of this
+     * annotation. See {@link #bv}.
+     */
+    private final ByteVector parent;
+
+    /**
+     * Where the number of values of this annotation must be stored in
+     * {@link #parent}.
+     */
+    private final int offset;
+
+    /**
+     * Next annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter next;
+
+    /**
+     * Previous annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter prev;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link AnnotationWriter}.
+     *
+     * @param cw the class writer to which this annotation must be added.
+     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+     * @param bv where the annotation values must be stored.
+     * @param parent where the number of annotation values must be stored.
+     * @param offset where in <tt>parent</tt> the number of annotation values must
+     *      be stored.
+     */
+    AnnotationWriter(
+        final ClassWriter cw,
+        final boolean named,
+        final ByteVector bv,
+        final ByteVector parent,
+        final int offset)
+    {
+        super(Opcodes.ASM4);
+        this.cw = cw;
+        this.named = named;
+        this.bv = bv;
+        this.parent = parent;
+        this.offset = offset;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the AnnotationVisitor abstract class
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final String name, final Object value) {
+        ++size;
+        if (named) {
+            bv.putShort(cw.newUTF8(name));
+        }
+        if (value instanceof String) {
+            bv.put12('s', cw.newUTF8((String) value));
+        } else if (value instanceof Byte) {
+            bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
+        } else if (value instanceof Boolean) {
+            int v = ((Boolean) value).booleanValue() ? 1 : 0;
+            bv.put12('Z', cw.newInteger(v).index);
+        } else if (value instanceof Character) {
+            bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
+        } else if (value instanceof Short) {
+            bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
+        } else if (value instanceof Type) {
+            bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
+        } else if (value instanceof byte[]) {
+            byte[] v = (byte[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('B', cw.newInteger(v[i]).index);
+            }
+        } else if (value instanceof boolean[]) {
+            boolean[] v = (boolean[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
+            }
+        } else if (value instanceof short[]) {
+            short[] v = (short[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('S', cw.newInteger(v[i]).index);
+            }
+        } else if (value instanceof char[]) {
+            char[] v = (char[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('C', cw.newInteger(v[i]).index);
+            }
+        } else if (value instanceof int[]) {
+            int[] v = (int[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('I', cw.newInteger(v[i]).index);
+            }
+        } else if (value instanceof long[]) {
+            long[] v = (long[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('J', cw.newLong(v[i]).index);
+            }
+        } else if (value instanceof float[]) {
+            float[] v = (float[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('F', cw.newFloat(v[i]).index);
+            }
+        } else if (value instanceof double[]) {
+            double[] v = (double[]) value;
+            bv.put12('[', v.length);
+            for (int i = 0; i < v.length; i++) {
+                bv.put12('D', cw.newDouble(v[i]).index);
+            }
+        } else {
+            Item i = cw.newConstItem(value);
+            bv.put12(".s.IFJDCS".charAt(i.type), i.index);
+        }
+    }
+
+    @Override
+    public void visitEnum(
+        final String name,
+        final String desc,
+        final String value)
+    {
+        ++size;
+        if (named) {
+            bv.putShort(cw.newUTF8(name));
+        }
+        bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(
+        final String name,
+        final String desc)
+    {
+        ++size;
+        if (named) {
+            bv.putShort(cw.newUTF8(name));
+        }
+        // write tag and type, and reserve space for values count
+        bv.put12('@', cw.newUTF8(desc)).putShort(0);
+        return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        ++size;
+        if (named) {
+            bv.putShort(cw.newUTF8(name));
+        }
+        // write tag, and reserve space for array size
+        bv.put12('[', 0);
+        return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+    }
+
+    @Override
+    public void visitEnd() {
+        if (parent != null) {
+            byte[] data = parent.data;
+            data[offset] = (byte) (size >>> 8);
+            data[offset + 1] = (byte) size;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of this annotation writer list.
+     *
+     * @return the size of this annotation writer list.
+     */
+    int getSize() {
+        int size = 0;
+        AnnotationWriter aw = this;
+        while (aw != null) {
+            size += aw.bv.length;
+            aw = aw.next;
+        }
+        return size;
+    }
+
+    /**
+     * Puts the annotations of this annotation writer list into the given byte
+     * vector.
+     *
+     * @param out where the annotations must be put.
+     */
+    void put(final ByteVector out) {
+        int n = 0;
+        int size = 2;
+        AnnotationWriter aw = this;
+        AnnotationWriter last = null;
+        while (aw != null) {
+            ++n;
+            size += aw.bv.length;
+            aw.visitEnd(); // in case user forgot to call visitEnd
+            aw.prev = last;
+            last = aw;
+            aw = aw.next;
+        }
+        out.putInt(size);
+        out.putShort(n);
+        aw = last;
+        while (aw != null) {
+            out.putByteArray(aw.bv.data, 0, aw.bv.length);
+            aw = aw.prev;
+        }
+    }
+
+    /**
+     * Puts the given annotation lists into the given byte vector.
+     *
+     * @param panns an array of annotation writer lists.
+     * @param off index of the first annotation to be written.
+     * @param out where the annotations must be put.
+     */
+    static void put(
+        final AnnotationWriter[] panns,
+        final int off,
+        final ByteVector out)
+    {
+        int size = 1 + 2 * (panns.length - off);
+        for (int i = off; i < panns.length; ++i) {
+            size += panns[i] == null ? 0 : panns[i].getSize();
+        }
+        out.putInt(size).putByte(panns.length - off);
+        for (int i = off; i < panns.length; ++i) {
+            AnnotationWriter aw = panns[i];
+            AnnotationWriter last = null;
+            int n = 0;
+            while (aw != null) {
+                ++n;
+                aw.visitEnd(); // in case user forgot to call visitEnd
+                aw.prev = last;
+                last = aw;
+                aw = aw.next;
+            }
+            out.putShort(n);
+            aw = last;
+            while (aw != null) {
+                out.putByteArray(aw.bv.data, 0, aw.bv.length);
+                aw = aw.prev;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Attribute.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,283 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+    /**
+     * The type of this attribute.
+     */
+    public final String type;
+
+    /**
+     * The raw value of this attribute, used only for unknown attributes.
+     */
+    byte[] value;
+
+    /**
+     * The next attribute in this attribute list. May be <tt>null</tt>.
+     */
+    Attribute next;
+
+    /**
+     * Constructs a new empty attribute.
+     *
+     * @param type the type of the attribute.
+     */
+    protected Attribute(final String type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is unknown. The default
+     * implementation of this method always returns <tt>true</tt>.
+     *
+     * @return <tt>true</tt> if this type of attribute is unknown.
+     */
+    public boolean isUnknown() {
+        return true;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is a code attribute.
+     *
+     * @return <tt>true</tt> if this type of attribute is a code attribute.
+     */
+    public boolean isCodeAttribute() {
+        return false;
+    }
+
+    /**
+     * Returns the labels corresponding to this attribute.
+     *
+     * @return the labels corresponding to this attribute, or <tt>null</tt> if
+     *         this attribute is not a code attribute that contains labels.
+     */
+    protected Label[] getLabels() {
+        return null;
+    }
+
+    /**
+     * Reads a {@link #type type} attribute. This method must return a <i>new</i>
+     * {@link Attribute} object, of type {@link #type type}, corresponding to
+     * the <tt>len</tt> bytes starting at the given offset, in the given class
+     * reader.
+     *
+     * @param cr the class that contains the attribute to be read.
+     * @param off index of the first byte of the attribute's content in {@link
+     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call
+     *        {@link ClassReader#readUTF8 readUTF8},
+     *        {@link ClassReader#readClass(int,char[]) readClass} or
+     *        {@link ClassReader#readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
+     *        not a code attribute. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return a <i>new</i> {@link Attribute} object corresponding to the given
+     *         bytes.
+     */
+    protected Attribute read(
+        final ClassReader cr,
+        final int off,
+        final int len,
+        final char[] buf,
+        final int codeOff,
+        final Label[] labels)
+    {
+        Attribute attr = new Attribute(type);
+        attr.value = new byte[len];
+        System.arraycopy(cr.b, off, attr.value, 0, len);
+        return attr;
+    }
+
+    /**
+     * Returns the byte array form of this attribute.
+     *
+     * @param cw the class to which this attribute must be added. This parameter
+     *        can be used to add to the constant pool of this class the items
+     *        that corresponds to this attribute.
+     * @param code the bytecode of the method corresponding to this code
+     *        attribute, or <tt>null</tt> if this attribute is not a code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to this
+     *        code attribute, or <tt>null</tt> if this attribute is not a code
+     *        attribute.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        this code attribute, or -1 if this attribute is not a code
+     *        attribute.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to this code attribute, or -1 if this attribute is
+     *        not a code attribute.
+     * @return the byte array form of this attribute.
+     */
+    protected ByteVector write(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals)
+    {
+        ByteVector v = new ByteVector();
+        v.data = value;
+        v.length = value.length;
+        return v;
+    }
+
+    /**
+     * Returns the length of the attribute list that begins with this attribute.
+     *
+     * @return the length of the attribute list that begins with this attribute.
+     */
+    final int getCount() {
+        int count = 0;
+        Attribute attr = this;
+        while (attr != null) {
+            count += 1;
+            attr = attr.next;
+        }
+        return count;
+    }
+
+    /**
+     * Returns the size of all the attributes in this attribute list.
+     *
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @return the size of all the attributes in this attribute list. This size
+     *         includes the size of the attribute headers.
+     */
+    final int getSize(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals)
+    {
+        Attribute attr = this;
+        int size = 0;
+        while (attr != null) {
+            cw.newUTF8(attr.type);
+            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
+            attr = attr.next;
+        }
+        return size;
+    }
+
+    /**
+     * Writes all the attributes of this attribute list in the given byte
+     * vector.
+     *
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @param out where the attributes must be written.
+     */
+    final void put(
+        final ClassWriter cw,
+        final byte[] code,
+        final int len,
+        final int maxStack,
+        final int maxLocals,
+        final ByteVector out)
+    {
+        Attribute attr = this;
+        while (attr != null) {
+            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
+            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
+            out.putByteArray(b.data, 0, b.length);
+            attr = attr.next;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,322 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ *
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+    /**
+     * The content of this vector.
+     */
+    byte[] data;
+
+    /**
+     * Actual number of bytes in this vector.
+     */
+    int length;
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with a default initial
+     * size.
+     */
+    public ByteVector() {
+        data = new byte[64];
+    }
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with the given initial
+     * size.
+     *
+     * @param initialSize the initial size of the byte vector to be constructed.
+     */
+    public ByteVector(final int initialSize) {
+        data = new byte[initialSize];
+    }
+
+    /**
+     * Puts a byte into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param b a byte.
+     * @return this byte vector.
+     */
+    public ByteVector putByte(final int b) {
+        int length = this.length;
+        if (length + 1 > data.length) {
+            enlarge(1);
+        }
+        data[length++] = (byte) b;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts two bytes into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param b1 a byte.
+     * @param b2 another byte.
+     * @return this byte vector.
+     */
+    ByteVector put11(final int b1, final int b2) {
+        int length = this.length;
+        if (length + 2 > data.length) {
+            enlarge(2);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) b1;
+        data[length++] = (byte) b2;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a short into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param s a short.
+     * @return this byte vector.
+     */
+    public ByteVector putShort(final int s) {
+        int length = this.length;
+        if (length + 2 > data.length) {
+            enlarge(2);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a byte and a short into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param b a byte.
+     * @param s a short.
+     * @return this byte vector.
+     */
+    ByteVector put12(final int b, final int s) {
+        int length = this.length;
+        if (length + 3 > data.length) {
+            enlarge(3);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) b;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an int into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param i an int.
+     * @return this byte vector.
+     */
+    public ByteVector putInt(final int i) {
+        int length = this.length;
+        if (length + 4 > data.length) {
+            enlarge(4);
+        }
+        byte[] data = this.data;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a long into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     *
+     * @param l a long.
+     * @return this byte vector.
+     */
+    public ByteVector putLong(final long l) {
+        int length = this.length;
+        if (length + 8 > data.length) {
+            enlarge(8);
+        }
+        byte[] data = this.data;
+        int i = (int) (l >>> 32);
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        i = (int) l;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an UTF8 string into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param s a String.
+     * @return this byte vector.
+     */
+    public ByteVector putUTF8(final String s) {
+        int charLength = s.length();
+        int len = length;
+        if (len + 2 + charLength > data.length) {
+            enlarge(2 + charLength);
+        }
+        byte[] data = this.data;
+        // optimistic algorithm: instead of computing the byte length and then
+        // serializing the string (which requires two loops), we assume the byte
+        // length is equal to char length (which is the most frequent case), and
+        // we start serializing the string right away. During the serialization,
+        // if we find that this assumption is wrong, we continue with the
+        // general method.
+        data[len++] = (byte) (charLength >>> 8);
+        data[len++] = (byte) charLength;
+        for (int i = 0; i < charLength; ++i) {
+            char c = s.charAt(i);
+            if (c >= '\001' && c <= '\177') {
+                data[len++] = (byte) c;
+            } else {
+                int byteLength = i;
+                for (int j = i; j < charLength; ++j) {
+                    c = s.charAt(j);
+                    if (c >= '\001' && c <= '\177') {
+                        byteLength++;
+                    } else if (c > '\u07FF') {
+                        byteLength += 3;
+                    } else {
+                        byteLength += 2;
+                    }
+                }
+                data[length] = (byte) (byteLength >>> 8);
+                data[length + 1] = (byte) byteLength;
+                if (length + 2 + byteLength > data.length) {
+                    length = len;
+                    enlarge(2 + byteLength);
+                    data = this.data;
+                }
+                for (int j = i; j < charLength; ++j) {
+                    c = s.charAt(j);
+                    if (c >= '\001' && c <= '\177') {
+                        data[len++] = (byte) c;
+                    } else if (c > '\u07FF') {
+                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    } else {
+                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    }
+                }
+                break;
+            }
+        }
+        length = len;
+        return this;
+    }
+
+    /**
+     * Puts an array of bytes into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     *
+     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+     *        null bytes into this byte vector.
+     * @param off index of the fist byte of b that must be copied.
+     * @param len number of bytes of b that must be copied.
+     * @return this byte vector.
+     */
+    public ByteVector putByteArray(final byte[] b, final int off, final int len)
+    {
+        if (length + len > data.length) {
+            enlarge(len);
+        }
+        if (b != null) {
+            System.arraycopy(b, off, data, length, len);
+        }
+        length += len;
+        return this;
+    }
+
+    /**
+     * Enlarge this byte vector so that it can receive n more bytes.
+     *
+     * @param size number of additional bytes that this byte vector should be
+     *        able to receive.
+     */
+    private void enlarge(final int size) {
+        int length1 = 2 * data.length;
+        int length2 = length + size;
+        byte[] newData = new byte[length1 > length2 ? length1 : length2];
+        System.arraycopy(data, 0, newData, 0, length);
+        data = newData;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,2245 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+    /**
+     * True to enable signatures support.
+     */
+    static final boolean SIGNATURES = true;
+
+    /**
+     * True to enable annotations support.
+     */
+    static final boolean ANNOTATIONS = true;
+
+    /**
+     * True to enable stack map frames support.
+     */
+    static final boolean FRAMES = true;
+
+    /**
+     * True to enable bytecode writing support.
+     */
+    static final boolean WRITER = true;
+
+    /**
+     * True to enable JSR_W and GOTO_W support.
+     */
+    static final boolean RESIZE = true;
+
+    /**
+     * Flag to skip method code. If this class is set <code>CODE</code>
+     * attribute won't be visited. This can be used, for example, to retrieve
+     * annotations for methods and method parameters.
+     */
+    public static final int SKIP_CODE = 1;
+
+    /**
+     * Flag to skip the debug information in the class. If this flag is set the
+     * debug information of the class is not visited, i.e. the
+     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+     * called.
+     */
+    public static final int SKIP_DEBUG = 2;
+
+    /**
+     * Flag to skip the stack map frames in the class. If this flag is set the
+     * stack map frames of the class is not visited, i.e. the
+     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+     * used: it avoids visiting frames that will be ignored and recomputed from
+     * scratch in the class writer.
+     */
+    public static final int SKIP_FRAMES = 4;
+
+    /**
+     * Flag to expand the stack map frames. By default stack map frames are
+     * visited in their original format (i.e. "expanded" for classes whose
+     * version is less than V1_6, and "compressed" for the other classes). If
+     * this flag is set, stack map frames are always visited in expanded format
+     * (this option adds a decompression/recompression step in ClassReader and
+     * ClassWriter which degrades performances quite a lot).
+     */
+    public static final int EXPAND_FRAMES = 8;
+
+    /**
+     * The class to be parsed. <i>The content of this array must not be
+     * modified. This field is intended for {@link Attribute} sub classes, and
+     * is normally not needed by class generators or adapters.</i>
+     */
+    public final byte[] b;
+
+    /**
+     * The start index of each constant pool item in {@link #b b}, plus one.
+     * The one byte offset skips the constant pool item tag that indicates its
+     * type.
+     */
+    private final int[] items;
+
+    /**
+     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+     * which GREATLY improves performances (by a factor 2 to 3). This caching
+     * strategy could be extended to all constant pool items, but its benefit
+     * would not be so great for these items (because they are much less
+     * expensive to parse than CONSTANT_Utf8 items).
+     */
+    private final String[] strings;
+
+    /**
+     * Maximum length of the strings contained in the constant pool of the
+     * class.
+     */
+    private final int maxStringLength;
+
+    /**
+     * Start index of the class header information (access, name...) in
+     * {@link #b b}.
+     */
+    public final int header;
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param b the bytecode of the class to be read.
+     */
+    public ClassReader(final byte[] b) {
+        this(b, 0, b.length);
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param b the bytecode of the class to be read.
+     * @param off the start offset of the class data.
+     * @param len the length of the class data.
+     */
+    public ClassReader(final byte[] b, final int off, final int len) {
+        this.b = b;
+        // checks the class version
+        if (readShort(6) > Opcodes.V1_7) {
+            throw new IllegalArgumentException();
+        }
+        // parses the constant pool
+        items = new int[readUnsignedShort(off + 8)];
+        int n = items.length;
+        strings = new String[n];
+        int max = 0;
+        int index = off + 10;
+        for (int i = 1; i < n; ++i) {
+            items[i] = index + 1;
+            int size;
+            switch (b[index]) {
+                case ClassWriter.FIELD:
+                case ClassWriter.METH:
+                case ClassWriter.IMETH:
+                case ClassWriter.INT:
+                case ClassWriter.FLOAT:
+                case ClassWriter.NAME_TYPE:
+                case ClassWriter.INDY:
+                    size = 5;
+                    break;
+                case ClassWriter.LONG:
+                case ClassWriter.DOUBLE:
+                    size = 9;
+                    ++i;
+                    break;
+                case ClassWriter.UTF8:
+                    size = 3 + readUnsignedShort(index + 1);
+                    if (size > max) {
+                        max = size;
+                    }
+                    break;
+                case ClassWriter.HANDLE:
+                    size = 4;
+                    break;
+                // case ClassWriter.CLASS:
+                // case ClassWriter.STR:
+                // case ClassWriter.MTYPE
+                default:
+                    size = 3;
+                    break;
+            }
+            index += size;
+        }
+        maxStringLength = max;
+        // the class header information starts just after the constant pool
+        header = index;
+    }
+
+    /**
+     * Returns the class's access flags (see {@link Opcodes}). This value may
+     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+     * and those flags are represented by attributes.
+     *
+     * @return the class access flags
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public int getAccess() {
+        return readUnsignedShort(header);
+    }
+
+    /**
+     * Returns the internal name of the class (see
+     * {@link Type#getInternalName() getInternalName}).
+     *
+     * @return the internal class name
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String getClassName() {
+        return readClass(header + 2, new char[maxStringLength]);
+    }
+
+    /**
+     * Returns the internal of name of the super class (see
+     * {@link Type#getInternalName() getInternalName}). For interfaces, the
+     * super class is {@link Object}.
+     *
+     * @return the internal name of super class, or <tt>null</tt> for
+     *         {@link Object} class.
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String getSuperName() {
+        int n = items[readUnsignedShort(header + 4)];
+        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+    }
+
+    /**
+     * Returns the internal names of the class's interfaces (see
+     * {@link Type#getInternalName() getInternalName}).
+     *
+     * @return the array of internal names for all implemented interfaces or
+     *         <tt>null</tt>.
+     *
+     * @see ClassVisitor#visit(int, int, String, String, String, String[])
+     */
+    public String[] getInterfaces() {
+        int index = header + 6;
+        int n = readUnsignedShort(index);
+        String[] interfaces = new String[n];
+        if (n > 0) {
+            char[] buf = new char[maxStringLength];
+            for (int i = 0; i < n; ++i) {
+                index += 2;
+                interfaces[i] = readClass(index, buf);
+            }
+        }
+        return interfaces;
+    }
+
+    /**
+     * Copies the constant pool data into the given {@link ClassWriter}. Should
+     * be called before the {@link #accept(ClassVisitor,int)} method.
+     *
+     * @param classWriter the {@link ClassWriter} to copy constant pool into.
+     */
+    void copyPool(final ClassWriter classWriter) {
+        char[] buf = new char[maxStringLength];
+        int ll = items.length;
+        Item[] items2 = new Item[ll];
+        for (int i = 1; i < ll; i++) {
+            int index = items[i];
+            int tag = b[index - 1];
+            Item item = new Item(i);
+            int nameType;
+            switch (tag) {
+                case ClassWriter.FIELD:
+                case ClassWriter.METH:
+                case ClassWriter.IMETH:
+                    nameType = items[readUnsignedShort(index + 2)];
+                    item.set(tag,
+                            readClass(index, buf),
+                            readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf));
+                    break;
+
+                case ClassWriter.INT:
+                    item.set(readInt(index));
+                    break;
+
+                case ClassWriter.FLOAT:
+                    item.set(Float.intBitsToFloat(readInt(index)));
+                    break;
+
+                case ClassWriter.NAME_TYPE:
+                    item.set(tag,
+                            readUTF8(index, buf),
+                            readUTF8(index + 2, buf),
+                            null);
+                    break;
+
+                case ClassWriter.LONG:
+                    item.set(readLong(index));
+                    ++i;
+                    break;
+
+                case ClassWriter.DOUBLE:
+                    item.set(Double.longBitsToDouble(readLong(index)));
+                    ++i;
+                    break;
+
+                case ClassWriter.UTF8: {
+                    String s = strings[i];
+                    if (s == null) {
+                        index = items[i];
+                        s = strings[i] = readUTF(index + 2,
+                                readUnsignedShort(index),
+                                buf);
+                    }
+                    item.set(tag, s, null, null);
+                }
+                    break;
+
+                case ClassWriter.HANDLE: {
+                    int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+                    nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+                    item.set(ClassWriter.HANDLE_BASE + readByte(index),
+                            readClass(fieldOrMethodRef, buf),
+                            readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf));
+
+                }
+                    break;
+
+
+                case ClassWriter.INDY:
+                    if (classWriter.bootstrapMethods == null) {
+                        copyBootstrapMethods(classWriter, items2, buf);
+                    }
+                    nameType = items[readUnsignedShort(index + 2)];
+                    item.set(readUTF8(nameType, buf),
+                            readUTF8(nameType + 2, buf),
+                            readUnsignedShort(index));
+                    break;
+
+
+                // case ClassWriter.STR:
+                // case ClassWriter.CLASS:
+                // case ClassWriter.MTYPE
+                default:
+                    item.set(tag, readUTF8(index, buf), null, null);
+                    break;
+            }
+
+            int index2 = item.hashCode % items2.length;
+            item.next = items2[index2];
+            items2[index2] = item;
+        }
+
+        int off = items[1] - 1;
+        classWriter.pool.putByteArray(b, off, header - off);
+        classWriter.items = items2;
+        classWriter.threshold = (int) (0.75d * ll);
+        classWriter.index = ll;
+    }
+
+    private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
+        int i, j, k, u, v;
+
+        // skip class header
+        v = header;
+        v += 8 + (readUnsignedShort(v + 6) << 1);
+
+        // skips fields and methods
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+
+        // read class attributes
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            String attrName = readUTF8(v, buf);
+            int size = readInt(v + 2);
+            if ("BootstrapMethods".equals(attrName)) {
+                int boostrapMethodCount = readUnsignedShort(v + 6);
+                int x = v + 8;
+                for (j = 0; j < boostrapMethodCount; j++) {
+                    int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
+                    k = readUnsignedShort(x + 2);
+                    u = x + 4;
+                    for(; k > 0; --k) {
+                        hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
+                        u += 2;
+                    }
+                    Item item = new Item(j);
+                    item.set(x - v - 8, hashCode & 0x7FFFFFFF);
+
+                    int index2 = item.hashCode % items2.length;
+                    item.next = items2[index2];
+                    items2[index2] = item;
+
+                    x = u;
+                }
+
+                classWriter.bootstrapMethodsCount = boostrapMethodCount;
+                ByteVector bootstrapMethods = new ByteVector(size + 62);
+                bootstrapMethods.putByteArray(b, v + 8, size - 2);
+                classWriter.bootstrapMethods = bootstrapMethods;
+                return;
+            }
+            v += 6 + size;
+        }
+
+        // we are in trouble !!!
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param is an input stream from which to read the class.
+     * @throws IOException if a problem occurs during reading.
+     */
+    public ClassReader(final InputStream is) throws IOException {
+        this(readClass(is, false));
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     *
+     * @param name the binary qualified name of the class to be read.
+     * @throws IOException if an exception occurs during reading.
+     */
+    public ClassReader(final String name) throws IOException {
+        this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+                + ".class"), true));
+    }
+
+    /**
+     * Reads the bytecode of a class.
+     *
+     * @param is an input stream from which to read the class.
+     * @param close true to close the input stream after reading.
+     * @return the bytecode read from the given input stream.
+     * @throws IOException if a problem occurs during reading.
+     */
+    private static byte[] readClass(final InputStream is, boolean close)
+            throws IOException
+    {
+        if (is == null) {
+            throw new IOException("Class not found");
+        }
+        try {
+            byte[] b = new byte[is.available()];
+            int len = 0;
+            while (true) {
+                int n = is.read(b, len, b.length - len);
+                if (n == -1) {
+                    if (len < b.length) {
+                        byte[] c = new byte[len];
+                        System.arraycopy(b, 0, c, 0, len);
+                        b = c;
+                    }
+                    return b;
+                }
+                len += n;
+                if (len == b.length) {
+                    int last = is.read();
+                    if (last < 0) {
+                        return b;
+                    }
+                    byte[] c = new byte[b.length + 1000];
+                    System.arraycopy(b, 0, c, 0, len);
+                    c[len++] = (byte) last;
+                    b = c;
+                }
+            }
+        } finally {
+            if (close) {
+                is.close();
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     *
+     * @param classVisitor the visitor that must visit this class.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     */
+    public void accept(final ClassVisitor classVisitor, final int flags) {
+        accept(classVisitor, new Attribute[0], flags);
+    }
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     *
+     * @param classVisitor the visitor that must visit this class.
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes will not be parsed: its byte array
+     *        value will be passed unchanged to the ClassWriter. <i>This may
+     *        corrupt it if this value contains references to the constant pool,
+     *        or has syntactic or semantic links with a class element that has
+     *        been transformed by a class adapter between the reader and the
+     *        writer</i>.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     */
+    public void accept(
+        final ClassVisitor classVisitor,
+        final Attribute[] attrs,
+        final int flags)
+    {
+        byte[] b = this.b; // the bytecode array
+        char[] c = new char[maxStringLength]; // buffer used to read strings
+        int i, j, k; // loop variables
+        int u, v, w; // indexes in b
+        Attribute attr;
+
+        int access;
+        String name;
+        String desc;
+        String attrName;
+        String signature;
+        int anns = 0;
+        int ianns = 0;
+        Attribute cattrs = null;
+
+        // visits the header
+        u = header;
+        access = readUnsignedShort(u);
+        name = readClass(u + 2, c);
+        v = items[readUnsignedShort(u + 4)];
+        String superClassName = v == 0 ? null : readUTF8(v, c);
+        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
+        w = 0;
+        u += 8;
+        for (i = 0; i < implementedItfs.length; ++i) {
+            implementedItfs[i] = readClass(u, c);
+            u += 2;
+        }
+
+        boolean skipCode = (flags & SKIP_CODE) != 0;
+        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
+        boolean unzip = (flags & EXPAND_FRAMES) != 0;
+
+        // skips fields and methods
+        v = u;
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            j = readUnsignedShort(v + 6);
+            v += 8;
+            for (; j > 0; --j) {
+                v += 6 + readInt(v + 2);
+            }
+        }
+        // reads the class's attributes
+        signature = null;
+        String sourceFile = null;
+        String sourceDebug = null;
+        String enclosingOwner = null;
+        String enclosingName = null;
+        String enclosingDesc = null;
+        int[] bootstrapMethods = null;  // start indexed of the bsms
+
+        i = readUnsignedShort(v);
+        v += 2;
+        for (; i > 0; --i) {
+            attrName = readUTF8(v, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("SourceFile".equals(attrName)) {
+                sourceFile = readUTF8(v + 6, c);
+            } else if ("InnerClasses".equals(attrName)) {
+                w = v + 6;
+            } else if ("EnclosingMethod".equals(attrName)) {
+                enclosingOwner = readClass(v + 6, c);
+                int item = readUnsignedShort(v + 8);
+                if (item != 0) {
+                    enclosingName = readUTF8(items[item], c);
+                    enclosingDesc = readUTF8(items[item] + 2, c);
+                }
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(v + 6, c);
+            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = v + 6;
+            } else if ("Deprecated".equals(attrName)) {
+                access |= Opcodes.ACC_DEPRECATED;
+            } else if ("Synthetic".equals(attrName)) {
+                access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if ("SourceDebugExtension".equals(attrName)) {
+                int len = readInt(v + 2);
+                sourceDebug = readUTF(v + 6, len, new char[len]);
+            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = v + 6;
+            } else if ("BootstrapMethods".equals(attrName)) {
+                int boostrapMethodCount = readUnsignedShort(v + 6);
+                bootstrapMethods = new int[boostrapMethodCount];
+                int x = v + 8;
+                for (j = 0; j < boostrapMethodCount; j++) {
+                    bootstrapMethods[j] = x;
+                    x += 2 + readUnsignedShort(x + 2) << 1;
+                }
+            } else {
+                attr = readAttribute(attrs,
+                        attrName,
+                        v + 6,
+                        readInt(v + 2),
+                        c,
+                        -1,
+                        null);
+                if (attr != null) {
+                    attr.next = cattrs;
+                    cattrs = attr;
+                }
+            }
+            v += 6 + readInt(v + 2);
+        }
+        // calls the visit method
+        classVisitor.visit(readInt(4),
+                access,
+                name,
+                signature,
+                superClassName,
+                implementedItfs);
+
+        // calls the visitSource method
+        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+            classVisitor.visitSource(sourceFile, sourceDebug);
+        }
+
+        // calls the visitOuterClass method
+        if (enclosingOwner != null) {
+            classVisitor.visitOuterClass(enclosingOwner,
+                    enclosingName,
+                    enclosingDesc);
+        }
+
+        // visits the class annotations
+        if (ANNOTATIONS) {
+            for (i = 1; i >= 0; --i) {
+                v = i == 0 ? ianns : anns;
+                if (v != 0) {
+                    j = readUnsignedShort(v);
+                    v += 2;
+                    for (; j > 0; --j) {
+                        v = readAnnotationValues(v + 2,
+                                c,
+                                true,
+                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
+                    }
+                }
+            }
+        }
+
+        // visits the class attributes
+        while (cattrs != null) {
+            attr = cattrs.next;
+            cattrs.next = null;
+            classVisitor.visitAttribute(cattrs);
+            cattrs = attr;
+        }
+
+        // calls the visitInnerClass method
+        if (w != 0) {
+            i = readUnsignedShort(w);
+            w += 2;
+            for (; i > 0; --i) {
+                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
+                        ? null
+                        : readClass(w, c), readUnsignedShort(w + 2) == 0
+                        ? null
+                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
+                        ? null
+                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
+                w += 8;
+            }
+        }
+
+        // visits the fields
+        i = readUnsignedShort(u);
+        u += 2;
+        for (; i > 0; --i) {
+            access = readUnsignedShort(u);
+            name = readUTF8(u + 2, c);
+            desc = readUTF8(u + 4, c);
+            // visits the field's attributes and looks for a ConstantValue
+            // attribute
+            int fieldValueItem = 0;
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            cattrs = null;
+
+            j = readUnsignedShort(u + 6);
+            u += 8;
+            for (; j > 0; --j) {
+                attrName = readUTF8(u, c);
+                // tests are sorted in decreasing frequency order
+                // (based on frequencies observed on typical classes)
+                if ("ConstantValue".equals(attrName)) {
+                    fieldValueItem = readUnsignedShort(u + 6);
+                } else if (SIGNATURES && "Signature".equals(attrName)) {
+                    signature = readUTF8(u + 6, c);
+                } else if ("Deprecated".equals(attrName)) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if ("Synthetic".equals(attrName)) {
+                    access |= Opcodes.ACC_SYNTHETIC  | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                    anns = u + 6;
+                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                    ianns = u + 6;
+                } else {
+                    attr = readAttribute(attrs,
+                            attrName,
+                            u + 6,
+                            readInt(u + 2),
+                            c,
+                            -1,
+                            null);
+                    if (attr != null) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += 6 + readInt(u + 2);
+            }
+            // visits the field
+            FieldVisitor fv = classVisitor.visitField(access,
+                    name,
+                    desc,
+                    signature,
+                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
+            // visits the field annotations and attributes
+            if (fv != null) {
+                if (ANNOTATIONS) {
+                    for (j = 1; j >= 0; --j) {
+                        v = j == 0 ? ianns : anns;
+                        if (v != 0) {
+                            k = readUnsignedShort(v);
+                            v += 2;
+                            for (; k > 0; --k) {
+                                v = readAnnotationValues(v + 2,
+                                        c,
+                                        true,
+                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
+                            }
+                        }
+                    }
+                }
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    fv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+                fv.visitEnd();
+            }
+        }
+
+        // visits the methods
+        i = readUnsignedShort(u);
+        u += 2;
+        for (; i > 0; --i) {
+            int u0 = u + 6;
+            access = readUnsignedShort(u);
+            name = readUTF8(u + 2, c);
+            desc = readUTF8(u + 4, c);
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            int dann = 0;
+            int mpanns = 0;
+            int impanns = 0;
+            cattrs = null;
+            v = 0;
+            w = 0;
+
+            // looks for Code and Exceptions attributes
+            j = readUnsignedShort(u + 6);
+            u += 8;
+            for (; j > 0; --j) {
+                attrName = readUTF8(u, c);
+                int attrSize = readInt(u + 2);
+                u += 6;
+                // tests are sorted in decreasing frequency order
+                // (based on frequencies observed on typical classes)
+                if ("Code".equals(attrName)) {
+                    if (!skipCode) {
+                        v = u;
+                    }
+                } else if ("Exceptions".equals(attrName)) {
+                    w = u;
+                } else if (SIGNATURES && "Signature".equals(attrName)) {
+                    signature = readUTF8(u, c);
+                } else if ("Deprecated".equals(attrName)) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+                    anns = u;
+                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+                    dann = u;
+                } else if ("Synthetic".equals(attrName)) {
+                    access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                    ianns = u;
+                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
+                {
+                    mpanns = u;
+                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
+                {
+                    impanns = u;
+                } else {
+                    attr = readAttribute(attrs,
+                            attrName,
+                            u,
+                            attrSize,
+                            c,
+                            -1,
+                            null);
+                    if (attr != null) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += attrSize;
+            }
+            // reads declared exceptions
+            String[] exceptions;
+            if (w == 0) {
+                exceptions = null;
+            } else {
+                exceptions = new String[readUnsignedShort(w)];
+                w += 2;
+                for (j = 0; j < exceptions.length; ++j) {
+                    exceptions[j] = readClass(w, c);
+                    w += 2;
+                }
+            }
+
+            // visits the method's code, if any
+            MethodVisitor mv = classVisitor.visitMethod(access,
+                    name,
+                    desc,
+                    signature,
+                    exceptions);
+
+            if (mv != null) {
+                /*
+                 * if the returned MethodVisitor is in fact a MethodWriter, it
+                 * means there is no method adapter between the reader and the
+                 * writer. If, in addition, the writer's constant pool was
+                 * copied from this reader (mw.cw.cr == this), and the signature
+                 * and exceptions of the method have not been changed, then it
+                 * is possible to skip all visit events and just copy the
+                 * original code of the method to the writer (the access, name
+                 * and descriptor can have been changed, this is not important
+                 * since they are not copied as is from the reader).
+                 */
+                if (WRITER && mv instanceof MethodWriter) {
+                    MethodWriter mw = (MethodWriter) mv;
+                    if (mw.cw.cr == this) {
+                        if (signature == mw.signature) {
+                            boolean sameExceptions = false;
+                            if (exceptions == null) {
+                                sameExceptions = mw.exceptionCount == 0;
+                            } else {
+                                if (exceptions.length == mw.exceptionCount) {
+                                    sameExceptions = true;
+                                    for (j = exceptions.length - 1; j >= 0; --j)
+                                    {
+                                        w -= 2;
+                                        if (mw.exceptions[j] != readUnsignedShort(w))
+                                        {
+                                            sameExceptions = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if (sameExceptions) {
+                                /*
+                                 * we do not copy directly the code into
+                                 * MethodWriter to save a byte array copy
+                                 * operation. The real copy will be done in
+                                 * ClassWriter.toByteArray().
+                                 */
+                                mw.classReaderOffset = u0;
+                                mw.classReaderLength = u - u0;
+                                continue;
+                            }
+                        }
+                    }
+                }
+
+                if (ANNOTATIONS && dann != 0) {
+                    AnnotationVisitor dv = mv.visitAnnotationDefault();
+                    readAnnotationValue(dann, c, null, dv);
+                    if (dv != null) {
+                        dv.visitEnd();
+                    }
+                }
+                if (ANNOTATIONS) {
+                    for (j = 1; j >= 0; --j) {
+                        w = j == 0 ? ianns : anns;
+                        if (w != 0) {
+                            k = readUnsignedShort(w);
+                            w += 2;
+                            for (; k > 0; --k) {
+                                w = readAnnotationValues(w + 2,
+                                        c,
+                                        true,
+                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
+                            }
+                        }
+                    }
+                }
+                if (ANNOTATIONS && mpanns != 0) {
+                    readParameterAnnotations(mpanns, desc, c, true, mv);
+                }
+                if (ANNOTATIONS && impanns != 0) {
+                    readParameterAnnotations(impanns, desc, c, false, mv);
+                }
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+            }
+
+            if (mv != null && v != 0) {
+                int maxStack = readUnsignedShort(v);
+                int maxLocals = readUnsignedShort(v + 2);
+                int codeLength = readInt(v + 4);
+                v += 8;
+
+                int codeStart = v;
+                int codeEnd = v + codeLength;
+
+                mv.visitCode();
+
+                // 1st phase: finds the labels
+                int label;
+                Label[] labels = new Label[codeLength + 2];
+                readLabel(codeLength + 1, labels);
+                while (v < codeEnd) {
+                    w = v - codeStart;
+                    int opcode = b[v] & 0xFF;
+                    switch (ClassWriter.TYPE[opcode]) {
+                        case ClassWriter.NOARG_INSN:
+                        case ClassWriter.IMPLVAR_INSN:
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN:
+                            readLabel(w + readShort(v + 1), labels);
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN:
+                            readLabel(w + readInt(v + 1), labels);
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN:
+                            opcode = b[v + 1] & 0xFF;
+                            if (opcode == Opcodes.IINC) {
+                                v += 6;
+                            } else {
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN:
+                            // skips 0 to 3 padding bytes*
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            readLabel(w + readInt(v), labels);
+                            j = readInt(v + 8) - readInt(v + 4) + 1;
+                            v += 12;
+                            for (; j > 0; --j) {
+                                readLabel(w + readInt(v), labels);
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.LOOK_INSN:
+                            // skips 0 to 3 padding bytes*
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            readLabel(w + readInt(v), labels);
+                            j = readInt(v + 4);
+                            v += 8;
+                            for (; j > 0; --j) {
+                                readLabel(w + readInt(v + 4), labels);
+                                v += 8;
+                            }
+                            break;
+                        case ClassWriter.VAR_INSN:
+                        case ClassWriter.SBYTE_INSN:
+                        case ClassWriter.LDC_INSN:
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN:
+                        case ClassWriter.LDCW_INSN:
+                        case ClassWriter.FIELDORMETH_INSN:
+                        case ClassWriter.TYPE_INSN:
+                        case ClassWriter.IINC_INSN:
+                            v += 3;
+                            break;
+                        case ClassWriter.ITFMETH_INSN:
+                        case ClassWriter.INDYMETH_INSN:
+                            v += 5;
+                            break;
+                        // case MANA_INSN:
+                        default:
+                            v += 4;
+                            break;
+                    }
+                }
+                // parses the try catch entries
+                j = readUnsignedShort(v);
+                v += 2;
+                for (; j > 0; --j) {
+                    Label start = readLabel(readUnsignedShort(v), labels);
+                    Label end = readLabel(readUnsignedShort(v + 2), labels);
+                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
+                    int type = readUnsignedShort(v + 6);
+                    if (type == 0) {
+                        mv.visitTryCatchBlock(start, end, handler, null);
+                    } else {
+                        mv.visitTryCatchBlock(start,
+                                end,
+                                handler,
+                                readUTF8(items[type], c));
+                    }
+                    v += 8;
+                }
+                // parses the local variable, line number tables, and code
+                // attributes
+                int varTable = 0;
+                int varTypeTable = 0;
+                int stackMap = 0;
+                int stackMapSize = 0;
+                int frameCount = 0;
+                int frameMode = 0;
+                int frameOffset = 0;
+                int frameLocalCount = 0;
+                int frameLocalDiff = 0;
+                int frameStackCount = 0;
+                Object[] frameLocal = null;
+                Object[] frameStack = null;
+                boolean zip = true;
+                cattrs = null;
+                j = readUnsignedShort(v);
+                v += 2;
+                for (; j > 0; --j) {
+                    attrName = readUTF8(v, c);
+                    if ("LocalVariableTable".equals(attrName)) {
+                        if (!skipDebug) {
+                            varTable = v + 6;
+                            k = readUnsignedShort(v + 6);
+                            w = v + 8;
+                            for (; k > 0; --k) {
+                                label = readUnsignedShort(w);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                label += readUnsignedShort(w + 2);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                w += 10;
+                            }
+                        }
+                    } else if ("LocalVariableTypeTable".equals(attrName)) {
+                        varTypeTable = v + 6;
+                    } else if ("LineNumberTable".equals(attrName)) {
+                        if (!skipDebug) {
+                            k = readUnsignedShort(v + 6);
+                            w = v + 8;
+                            for (; k > 0; --k) {
+                                label = readUnsignedShort(w);
+                                if (labels[label] == null) {
+                                    readLabel(label, labels).status |= Label.DEBUG;
+                                }
+                                labels[label].line = readUnsignedShort(w + 2);
+                                w += 4;
+                            }
+                        }
+                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
+                        if ((flags & SKIP_FRAMES) == 0) {
+                            stackMap = v + 8;
+                            stackMapSize = readInt(v + 2);
+                            frameCount = readUnsignedShort(v + 6);
+                        }
+                        /*
+                         * here we do not extract the labels corresponding to
+                         * the attribute content. This would require a full
+                         * parsing of the attribute, which would need to be
+                         * repeated in the second phase (see below). Instead the
+                         * content of the attribute is read one frame at a time
+                         * (i.e. after a frame has been visited, the next frame
+                         * is read), and the labels it contains are also
+                         * extracted one frame at a time. Thanks to the ordering
+                         * of frames, having only a "one frame lookahead" is not
+                         * a problem, i.e. it is not possible to see an offset
+                         * smaller than the offset of the current insn and for
+                         * which no Label exist.
+                         */
+                        /*
+                         * This is not true for UNINITIALIZED type offsets. We
+                         * solve this by parsing the stack map table without a
+                         * full decoding (see below).
+                         */
+                    } else if (FRAMES && "StackMap".equals(attrName)) {
+                        if ((flags & SKIP_FRAMES) == 0) {
+                            stackMap = v + 8;
+                            stackMapSize = readInt(v + 2);
+                            frameCount = readUnsignedShort(v + 6);
+                            zip = false;
+                        }
+                        /*
+                         * IMPORTANT! here we assume that the frames are
+                         * ordered, as in the StackMapTable attribute, although
+                         * this is not guaranteed by the attribute format.
+                         */
+                    } else {
+                        for (k = 0; k < attrs.length; ++k) {
+                            if (attrs[k].type.equals(attrName)) {
+                                attr = attrs[k].read(this,
+                                        v + 6,
+                                        readInt(v + 2),
+                                        c,
+                                        codeStart - 8,
+                                        labels);
+                                if (attr != null) {
+                                    attr.next = cattrs;
+                                    cattrs = attr;
+                                }
+                            }
+                        }
+                    }
+                    v += 6 + readInt(v + 2);
+                }
+
+                // 2nd phase: visits each instruction
+                if (FRAMES && stackMap != 0) {
+                    // creates the very first (implicit) frame from the method
+                    // descriptor
+                    frameLocal = new Object[maxLocals];
+                    frameStack = new Object[maxStack];
+                    if (unzip) {
+                        int local = 0;
+                        if ((access & Opcodes.ACC_STATIC) == 0) {
+                            if ("<init>".equals(name)) {
+                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
+                            } else {
+                                frameLocal[local++] = readClass(header + 2, c);
+                            }
+                        }
+                        j = 1;
+                        loop: while (true) {
+                            k = j;
+                            switch (desc.charAt(j++)) {
+                                case 'Z':
+                                case 'C':
+                                case 'B':
+                                case 'S':
+                                case 'I':
+                                    frameLocal[local++] = Opcodes.INTEGER;
+                                    break;
+                                case 'F':
+                                    frameLocal[local++] = Opcodes.FLOAT;
+                                    break;
+                                case 'J':
+                                    frameLocal[local++] = Opcodes.LONG;
+                                    break;
+                                case 'D':
+                                    frameLocal[local++] = Opcodes.DOUBLE;
+                                    break;
+                                case '[':
+                                    while (desc.charAt(j) == '[') {
+                                        ++j;
+                                    }
+                                    if (desc.charAt(j) == 'L') {
+                                        ++j;
+                                        while (desc.charAt(j) != ';') {
+                                            ++j;
+                                        }
+                                    }
+                                    frameLocal[local++] = desc.substring(k, ++j);
+                                    break;
+                                case 'L':
+                                    while (desc.charAt(j) != ';') {
+                                        ++j;
+                                    }
+                                    frameLocal[local++] = desc.substring(k + 1,
+                                            j++);
+                                    break;
+                                default:
+                                    break loop;
+                            }
+                        }
+                        frameLocalCount = local;
+                    }
+                    /*
+                     * for the first explicit frame the offset is not
+                     * offset_delta + 1 but only offset_delta; setting the
+                     * implicit frame offset to -1 allow the use of the
+                     * "offset_delta + 1" rule in all cases
+                     */
+                    frameOffset = -1;
+                    /*
+                     * Finds labels for UNINITIALIZED frame types. Instead of
+                     * decoding each element of the stack map table, we look
+                     * for 3 consecutive bytes that "look like" an UNINITIALIZED
+                     * type (tag 8, offset within code bounds, NEW instruction
+                     * at this offset). We may find false positives (i.e. not
+                     * real UNINITIALIZED types), but this should be rare, and
+                     * the only consequence will be the creation of an unneeded
+                     * label. This is better than creating a label for each NEW
+                     * instruction, and faster than fully decoding the whole
+                     * stack map table.
+                     */
+                    for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
+                        if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
+                            k = readUnsignedShort(j + 1);
+                            if (k >= 0 && k < codeLength) { // potential offset
+                                if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
+                                    readLabel(k, labels);
+                                }
+                            }
+                        }
+                    }
+                }
+                v = codeStart;
+                Label l;
+                while (v < codeEnd) {
+                    w = v - codeStart;
+
+                    l = labels[w];
+                    if (l != null) {
+                        mv.visitLabel(l);
+                        if (!skipDebug && l.line > 0) {
+                            mv.visitLineNumber(l.line, l);
+                        }
+                    }
+
+                    while (FRAMES && frameLocal != null
+                            && (frameOffset == w || frameOffset == -1))
+                    {
+                        // if there is a frame for this offset,
+                        // makes the visitor visit it,
+                        // and reads the next frame if there is one.
+                        if (!zip || unzip) {
+                            mv.visitFrame(Opcodes.F_NEW,
+                                    frameLocalCount,
+                                    frameLocal,
+                                    frameStackCount,
+                                    frameStack);
+                        } else if (frameOffset != -1) {
+                            mv.visitFrame(frameMode,
+                                    frameLocalDiff,
+                                    frameLocal,
+                                    frameStackCount,
+                                    frameStack);
+                        }
+
+                        if (frameCount > 0) {
+                            int tag, delta, n;
+                            if (zip) {
+                                tag = b[stackMap++] & 0xFF;
+                            } else {
+                                tag = MethodWriter.FULL_FRAME;
+                                frameOffset = -1;
+                            }
+                            frameLocalDiff = 0;
+                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
+                            {
+                                delta = tag;
+                                frameMode = Opcodes.F_SAME;
+                                frameStackCount = 0;
+                            } else if (tag < MethodWriter.RESERVED) {
+                                delta = tag
+                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+                                stackMap = readFrameType(frameStack,
+                                        0,
+                                        stackMap,
+                                        c,
+                                        labels);
+                                frameMode = Opcodes.F_SAME1;
+                                frameStackCount = 1;
+                            } else {
+                                delta = readUnsignedShort(stackMap);
+                                stackMap += 2;
+                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+                                {
+                                    stackMap = readFrameType(frameStack,
+                                            0,
+                                            stackMap,
+                                            c,
+                                            labels);
+                                    frameMode = Opcodes.F_SAME1;
+                                    frameStackCount = 1;
+                                } else if (tag >= MethodWriter.CHOP_FRAME
+                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
+                                {
+                                    frameMode = Opcodes.F_CHOP;
+                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
+                                            - tag;
+                                    frameLocalCount -= frameLocalDiff;
+                                    frameStackCount = 0;
+                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
+                                {
+                                    frameMode = Opcodes.F_SAME;
+                                    frameStackCount = 0;
+                                } else if (tag < MethodWriter.FULL_FRAME) {
+                                    j = unzip ? frameLocalCount : 0;
+                                    for (k = tag
+                                            - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
+                                    {
+                                        stackMap = readFrameType(frameLocal,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                    frameMode = Opcodes.F_APPEND;
+                                    frameLocalDiff = tag
+                                            - MethodWriter.SAME_FRAME_EXTENDED;
+                                    frameLocalCount += frameLocalDiff;
+                                    frameStackCount = 0;
+                                } else { // if (tag == FULL_FRAME) {
+                                    frameMode = Opcodes.F_FULL;
+                                    n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
+                                    stackMap += 2;
+                                    for (j = 0; n > 0; n--) {
+                                        stackMap = readFrameType(frameLocal,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                    n = frameStackCount = readUnsignedShort(stackMap);
+                                    stackMap += 2;
+                                    for (j = 0; n > 0; n--) {
+                                        stackMap = readFrameType(frameStack,
+                                                j++,
+                                                stackMap,
+                                                c,
+                                                labels);
+                                    }
+                                }
+                            }
+                            frameOffset += delta + 1;
+                            readLabel(frameOffset, labels);
+
+                            --frameCount;
+                        } else {
+                            frameLocal = null;
+                        }
+                    }
+
+                    int opcode = b[v] & 0xFF;
+                    switch (ClassWriter.TYPE[opcode]) {
+                        case ClassWriter.NOARG_INSN:
+                            mv.visitInsn(opcode);
+                            v += 1;
+                            break;
+                        case ClassWriter.IMPLVAR_INSN:
+                            if (opcode > Opcodes.ISTORE) {
+                                opcode -= 59; // ISTORE_0
+                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
+                                        opcode & 0x3);
+                            } else {
+                                opcode -= 26; // ILOAD_0
+                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
+                                        opcode & 0x3);
+                            }
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN:
+                            mv.visitJumpInsn(opcode, labels[w
+                                    + readShort(v + 1)]);
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN:
+                            mv.visitJumpInsn(opcode - 33, labels[w
+                                    + readInt(v + 1)]);
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN:
+                            opcode = b[v + 1] & 0xFF;
+                            if (opcode == Opcodes.IINC) {
+                                mv.visitIincInsn(readUnsignedShort(v + 2),
+                                        readShort(v + 4));
+                                v += 6;
+                            } else {
+                                mv.visitVarInsn(opcode,
+                                        readUnsignedShort(v + 2));
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN:
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt(v);
+                            int min = readInt(v + 4);
+                            int max = readInt(v + 8);
+                            v += 12;
+                            Label[] table = new Label[max - min + 1];
+                            for (j = 0; j < table.length; ++j) {
+                                table[j] = labels[w + readInt(v)];
+                                v += 4;
+                            }
+                            mv.visitTableSwitchInsn(min,
+                                    max,
+                                    labels[label],
+                                    table);
+                            break;
+                        case ClassWriter.LOOK_INSN:
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt(v);
+                            j = readInt(v + 4);
+                            v += 8;
+                            int[] keys = new int[j];
+                            Label[] values = new Label[j];
+                            for (j = 0; j < keys.length; ++j) {
+                                keys[j] = readInt(v);
+                                values[j] = labels[w + readInt(v + 4)];
+                                v += 8;
+                            }
+                            mv.visitLookupSwitchInsn(labels[label],
+                                    keys,
+                                    values);
+                            break;
+                        case ClassWriter.VAR_INSN:
+                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
+                            v += 2;
+                            break;
+                        case ClassWriter.SBYTE_INSN:
+                            mv.visitIntInsn(opcode, b[v + 1]);
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN:
+                            mv.visitIntInsn(opcode, readShort(v + 1));
+                            v += 3;
+                            break;
+                        case ClassWriter.LDC_INSN:
+                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
+                            v += 2;
+                            break;
+                        case ClassWriter.LDCW_INSN:
+                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
+                                    c));
+                            v += 3;
+                            break;
+                        case ClassWriter.FIELDORMETH_INSN:
+                        case ClassWriter.ITFMETH_INSN: {
+                            int cpIndex = items[readUnsignedShort(v + 1)];
+                            String iowner = readClass(cpIndex, c);
+                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                            String iname = readUTF8(cpIndex, c);
+                            String idesc = readUTF8(cpIndex + 2, c);
+                            if (opcode < Opcodes.INVOKEVIRTUAL) {
+                                mv.visitFieldInsn(opcode, iowner, iname, idesc);
+                            } else {
+                                mv.visitMethodInsn(opcode, iowner, iname, idesc);
+                            }
+                            if (opcode == Opcodes.INVOKEINTERFACE) {
+                                v += 5;
+                            } else {
+                                v += 3;
+                            }
+                            break;
+                        }
+                        case ClassWriter.INDYMETH_INSN: {
+                            int cpIndex = items[readUnsignedShort(v + 1)];
+                            int bsmIndex = bootstrapMethods[readUnsignedShort(cpIndex)];
+                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                            String iname = readUTF8(cpIndex, c);
+                            String idesc = readUTF8(cpIndex + 2, c);
+
+                            int mhIndex = readUnsignedShort(bsmIndex);
+                            Handle bsm = (Handle) readConst(mhIndex, c);
+                            int bsmArgCount = readUnsignedShort(bsmIndex + 2);
+                            Object[] bsmArgs = new Object[bsmArgCount];
+                            bsmIndex += 4;
+                            for(int a = 0; a < bsmArgCount; a++) {
+                                int argIndex = readUnsignedShort(bsmIndex);
+                                bsmArgs[a] = readConst(argIndex, c);
+                                bsmIndex += 2;
+                            }
+                            mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
+
+                            v += 5;
+                            break;
+                        }
+                        case ClassWriter.TYPE_INSN:
+                            mv.visitTypeInsn(opcode, readClass(v + 1, c));
+                            v += 3;
+                            break;
+                        case ClassWriter.IINC_INSN:
+                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
+                            v += 3;
+                            break;
+                        // case MANA_INSN:
+                        default:
+                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),
+                                    b[v + 3] & 0xFF);
+                            v += 4;
+                            break;
+                    }
+                }
+                l = labels[codeEnd - codeStart];
+                if (l != null) {
+                    mv.visitLabel(l);
+                }
+                // visits the local variable tables
+                if (!skipDebug && varTable != 0) {
+                    int[] typeTable = null;
+                    if (varTypeTable != 0) {
+                        k = readUnsignedShort(varTypeTable) * 3;
+                        w = varTypeTable + 2;
+                        typeTable = new int[k];
+                        while (k > 0) {
+                            typeTable[--k] = w + 6; // signature
+                            typeTable[--k] = readUnsignedShort(w + 8); // index
+                            typeTable[--k] = readUnsignedShort(w); // start
+                            w += 10;
+                        }
+                    }
+                    k = readUnsignedShort(varTable);
+                    w = varTable + 2;
+                    for (; k > 0; --k) {
+                        int start = readUnsignedShort(w);
+                        int length = readUnsignedShort(w + 2);
+                        int index = readUnsignedShort(w + 8);
+                        String vsignature = null;
+                        if (typeTable != null) {
+                            for (int a = 0; a < typeTable.length; a += 3) {
+                                if (typeTable[a] == start
+                                        && typeTable[a + 1] == index)
+                                {
+                                    vsignature = readUTF8(typeTable[a + 2], c);
+                                    break;
+                                }
+                            }
+                        }
+                        mv.visitLocalVariable(readUTF8(w + 4, c),
+                                readUTF8(w + 6, c),
+                                vsignature,
+                                labels[start],
+                                labels[start + length],
+                                index);
+                        w += 10;
+                    }
+                }
+                // visits the other attributes
+                while (cattrs != null) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute(cattrs);
+                    cattrs = attr;
+                }
+                // visits the max stack and max locals values
+                mv.visitMaxs(maxStack, maxLocals);
+            }
+
+            if (mv != null) {
+                mv.visitEnd();
+            }
+        }
+
+        // visits the end of the class
+        classVisitor.visitEnd();
+    }
+
+    /**
+     * Reads parameter annotations and makes the given visitor visit them.
+     *
+     * @param v start offset in {@link #b b} of the annotations to be read.
+     * @param desc the method descriptor.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param visible <tt>true</tt> if the annotations to be read are visible
+     *        at runtime.
+     * @param mv the visitor that must visit the annotations.
+     */
+    private void readParameterAnnotations(
+        int v,
+        final String desc,
+        final char[] buf,
+        final boolean visible,
+        final MethodVisitor mv)
+    {
+        int i;
+        int n = b[v++] & 0xFF;
+        // workaround for a bug in javac (javac compiler generates a parameter
+        // annotation array whose size is equal to the number of parameters in
+        // the Java source file, while it should generate an array whose size is
+        // equal to the number of parameters in the method descriptor - which
+        // includes the synthetic parameters added by the compiler). This work-
+        // around supposes that the synthetic parameters are the first ones.
+        int synthetics = Type.getArgumentTypes(desc).length - n;
+        AnnotationVisitor av;
+        for (i = 0; i < synthetics; ++i) {
+            // virtual annotation to detect synthetic parameters in MethodWriter
+            av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+        for (; i < n + synthetics; ++i) {
+            int j = readUnsignedShort(v);
+            v += 2;
+            for (; j > 0; --j) {
+                av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
+                v = readAnnotationValues(v + 2, buf, true, av);
+            }
+        }
+    }
+
+    /**
+     * Reads the values of an annotation and makes the given visitor visit them.
+     *
+     * @param v the start offset in {@link #b b} of the values to be read
+     *        (including the unsigned short that gives the number of values).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param named if the annotation values are named or not.
+     * @param av the visitor that must visit the values.
+     * @return the end offset of the annotation values.
+     */
+    private int readAnnotationValues(
+        int v,
+        final char[] buf,
+        final boolean named,
+        final AnnotationVisitor av)
+    {
+        int i = readUnsignedShort(v);
+        v += 2;
+        if (named) {
+            for (; i > 0; --i) {
+                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+            }
+        } else {
+            for (; i > 0; --i) {
+                v = readAnnotationValue(v, buf, null, av);
+            }
+        }
+        if (av != null) {
+            av.visitEnd();
+        }
+        return v;
+    }
+
+    /**
+     * Reads a value of an annotation and makes the given visitor visit it.
+     *
+     * @param v the start offset in {@link #b b} of the value to be read (<i>not
+     *        including the value name constant pool index</i>).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param name the name of the value to be read.
+     * @param av the visitor that must visit the value.
+     * @return the end offset of the annotation value.
+     */
+    private int readAnnotationValue(
+        int v,
+        final char[] buf,
+        final String name,
+        final AnnotationVisitor av)
+    {
+        int i;
+        if (av == null) {
+            switch (b[v] & 0xFF) {
+                case 'e': // enum_const_value
+                    return v + 5;
+                case '@': // annotation_value
+                    return readAnnotationValues(v + 3, buf, true, null);
+                case '[': // array_value
+                    return readAnnotationValues(v + 1, buf, false, null);
+                default:
+                    return v + 3;
+            }
+        }
+        switch (b[v++] & 0xFF) {
+            case 'I': // pointer to CONSTANT_Integer
+            case 'J': // pointer to CONSTANT_Long
+            case 'F': // pointer to CONSTANT_Float
+            case 'D': // pointer to CONSTANT_Double
+                av.visit(name, readConst(readUnsignedShort(v), buf));
+                v += 2;
+                break;
+            case 'B': // pointer to CONSTANT_Byte
+                av.visit(name,
+                        new Byte((byte) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 'Z': // pointer to CONSTANT_Boolean
+                av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
+                        ? Boolean.FALSE
+                        : Boolean.TRUE);
+                v += 2;
+                break;
+            case 'S': // pointer to CONSTANT_Short
+                av.visit(name,
+                        new Short((short) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 'C': // pointer to CONSTANT_Char
+                av.visit(name,
+                        new Character((char) readInt(items[readUnsignedShort(v)])));
+                v += 2;
+                break;
+            case 's': // pointer to CONSTANT_Utf8
+                av.visit(name, readUTF8(v, buf));
+                v += 2;
+                break;
+            case 'e': // enum_const_value
+                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+                v += 4;
+                break;
+            case 'c': // class_info
+                av.visit(name, Type.getType(readUTF8(v, buf)));
+                v += 2;
+                break;
+            case '@': // annotation_value
+                v = readAnnotationValues(v + 2,
+                        buf,
+                        true,
+                        av.visitAnnotation(name, readUTF8(v, buf)));
+                break;
+            case '[': // array_value
+                int size = readUnsignedShort(v);
+                v += 2;
+                if (size == 0) {
+                    return readAnnotationValues(v - 2,
+                            buf,
+                            false,
+                            av.visitArray(name));
+                }
+                switch (this.b[v++] & 0xFF) {
+                    case 'B':
+                        byte[] bv = new byte[size];
+                        for (i = 0; i < size; i++) {
+                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, bv);
+                        --v;
+                        break;
+                    case 'Z':
+                        boolean[] zv = new boolean[size];
+                        for (i = 0; i < size; i++) {
+                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+                            v += 3;
+                        }
+                        av.visit(name, zv);
+                        --v;
+                        break;
+                    case 'S':
+                        short[] sv = new short[size];
+                        for (i = 0; i < size; i++) {
+                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, sv);
+                        --v;
+                        break;
+                    case 'C':
+                        char[] cv = new char[size];
+                        for (i = 0; i < size; i++) {
+                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, cv);
+                        --v;
+                        break;
+                    case 'I':
+                        int[] iv = new int[size];
+                        for (i = 0; i < size; i++) {
+                            iv[i] = readInt(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, iv);
+                        --v;
+                        break;
+                    case 'J':
+                        long[] lv = new long[size];
+                        for (i = 0; i < size; i++) {
+                            lv[i] = readLong(items[readUnsignedShort(v)]);
+                            v += 3;
+                        }
+                        av.visit(name, lv);
+                        --v;
+                        break;
+                    case 'F':
+                        float[] fv = new float[size];
+                        for (i = 0; i < size; i++) {
+                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+                            v += 3;
+                        }
+                        av.visit(name, fv);
+                        --v;
+                        break;
+                    case 'D':
+                        double[] dv = new double[size];
+                        for (i = 0; i < size; i++) {
+                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+                            v += 3;
+                        }
+                        av.visit(name, dv);
+                        --v;
+                        break;
+                    default:
+                        v = readAnnotationValues(v - 3,
+                                buf,
+                                false,
+                                av.visitArray(name));
+                }
+        }
+        return v;
+    }
+
+    private int readFrameType(
+        final Object[] frame,
+        final int index,
+        int v,
+        final char[] buf,
+        final Label[] labels)
+    {
+        int type = b[v++] & 0xFF;
+        switch (type) {
+            case 0:
+                frame[index] = Opcodes.TOP;
+                break;
+            case 1:
+                frame[index] = Opcodes.INTEGER;
+                break;
+            case 2:
+                frame[index] = Opcodes.FLOAT;
+                break;
+            case 3:
+                frame[index] = Opcodes.DOUBLE;
+                break;
+            case 4:
+                frame[index] = Opcodes.LONG;
+                break;
+            case 5:
+                frame[index] = Opcodes.NULL;
+                break;
+            case 6:
+                frame[index] = Opcodes.UNINITIALIZED_THIS;
+                break;
+            case 7: // Object
+                frame[index] = readClass(v, buf);
+                v += 2;
+                break;
+            default: // Uninitialized
+                frame[index] = readLabel(readUnsignedShort(v), labels);
+                v += 2;
+        }
+        return v;
+    }
+
+    /**
+     * Returns the label corresponding to the given offset. The default
+     * implementation of this method creates a label for the given offset if it
+     * has not been already created.
+     *
+     * @param offset a bytecode offset in a method.
+     * @param labels the already created labels, indexed by their offset. If a
+     *        label already exists for offset this method must not create a new
+     *        one. Otherwise it must store the new label in this array.
+     * @return a non null Label, which must be equal to labels[offset].
+     */
+    protected Label readLabel(int offset, Label[] labels) {
+        if (labels[offset] == null) {
+            labels[offset] = new Label();
+        }
+        return labels[offset];
+    }
+
+    /**
+     * Reads an attribute in {@link #b b}.
+     *
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes is ignored (i.e. an empty
+     *        {@link Attribute} instance is returned).
+     * @param type the type of the attribute.
+     * @param off index of the first byte of the attribute's content in
+     *        {@link #b b}. The 6 attribute header bytes, containing the type
+     *        and the length of the attribute, are not taken into account here
+     *        (they have already been read).
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link #b b}, or -1 if the attribute to be read is not a code
+     *        attribute. The 6 attribute header bytes, containing the type and
+     *        the length of the attribute, are not taken into account here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return the attribute that has been read, or <tt>null</tt> to skip this
+     *         attribute.
+     */
+    private Attribute readAttribute(
+        final Attribute[] attrs,
+        final String type,
+        final int off,
+        final int len,
+        final char[] buf,
+        final int codeOff,
+        final Label[] labels)
+    {
+        for (int i = 0; i < attrs.length; ++i) {
+            if (attrs[i].type.equals(type)) {
+                return attrs[i].read(this, off, len, buf, codeOff, labels);
+            }
+        }
+        return new Attribute(type).read(this, off, len, null, -1, null);
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: low level parsing
+    // ------------------------------------------------------------------------
+
+    /**
+     *  Returns the number of constant pool items in {@link #b b}.
+     *
+     *  @return the number of constant pool items in {@link #b b}.
+     */
+    public int getItemCount() {
+        return items.length;
+    }
+
+    /**
+     * Returns the start index of the constant pool item in {@link #b b}, plus
+     * one. <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param item the index a constant pool item.
+     * @return the start index of the constant pool item in {@link #b b}, plus
+     *         one.
+     */
+    public int getItem(final int item) {
+        return items[item];
+    }
+
+    /**
+     * Returns the maximum length of the strings contained in the constant pool
+     * of the class.
+     *
+     * @return the maximum length of the strings contained in the constant pool
+     *         of the class.
+     */
+    public int getMaxStringLength() {
+        return maxStringLength;
+    }
+
+    /**
+     * Reads a byte value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readByte(final int index) {
+        return b[index] & 0xFF;
+    }
+
+    /**
+     * Reads an unsigned short value in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readUnsignedShort(final int index) {
+        byte[] b = this.b;
+        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+    }
+
+    /**
+     * Reads a signed short value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public short readShort(final int index) {
+        byte[] b = this.b;
+        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+    }
+
+    /**
+     * Reads a signed int value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readInt(final int index) {
+        byte[] b = this.b;
+        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+    }
+
+    /**
+     * Reads a signed long value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     *
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public long readLong(final int index) {
+        long l1 = readInt(index);
+        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+        return (l1 << 32) | l0;
+    }
+
+    /**
+     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+     * is intended for {@link Attribute} sub classes, and is normally not needed
+     * by class generators or adapters.</i>
+     *
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of an UTF8 constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 item.
+     */
+    public String readUTF8(int index, final char[] buf) {
+        int item = readUnsignedShort(index);
+        String s = strings[item];
+        if (s != null) {
+            return s;
+        }
+        index = items[item];
+        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+    }
+
+    /**
+     * Reads UTF8 string in {@link #b b}.
+     *
+     * @param index start offset of the UTF8 string to be read.
+     * @param utfLen length of the UTF8 string to be read.
+     * @param buf buffer to be used to read the string. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 string.
+     */
+    private String readUTF(int index, final int utfLen, final char[] buf) {
+        int endIndex = index + utfLen;
+        byte[] b = this.b;
+        int strLen = 0;
+        int c;
+        int st = 0;
+        char cc = 0;
+        while (index < endIndex) {
+            c = b[index++];
+            switch (st) {
+                case 0:
+                    c = c & 0xFF;
+                    if (c < 0x80) {  // 0xxxxxxx
+                        buf[strLen++] = (char) c;
+                    } else if (c < 0xE0 && c > 0xBF) {  // 110x xxxx 10xx xxxx
+                        cc = (char) (c & 0x1F);
+                        st = 1;
+                    } else {  // 1110 xxxx 10xx xxxx 10xx xxxx
+                        cc = (char) (c & 0x0F);
+                        st = 2;
+                    }
+                    break;
+
+                case 1:  // byte 2 of 2-byte char or byte 3 of 3-byte char
+                    buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+                    st = 0;
+                    break;
+
+                case 2:  // byte 2 of 3-byte char
+                    cc = (char) ((cc << 6) | (c & 0x3F));
+                    st = 1;
+                    break;
+            }
+        }
+        return new String(buf, 0, strLen);
+    }
+
+    /**
+     * Reads a class constant pool item in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of a class constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified class item.
+     */
+    public String readClass(final int index, final char[] buf) {
+        // computes the start index of the CONSTANT_Class item in b
+        // and reads the CONSTANT_Utf8 item designated by
+        // the first two bytes of this CONSTANT_Class item
+        return readUTF8(items[readUnsignedShort(index)], buf);
+    }
+
+    /**
+     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param item the index of a constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
+     *         {@link String}, {@link Type} or {@link Handle} corresponding to
+     *         the given constant pool item.
+     */
+    public Object readConst(final int item, final char[] buf) {
+        int index = items[item];
+        switch (b[index - 1]) {
+            case ClassWriter.INT:
+                return new Integer(readInt(index));
+            case ClassWriter.FLOAT:
+                return new Float(Float.intBitsToFloat(readInt(index)));
+            case ClassWriter.LONG:
+                return new Long(readLong(index));
+            case ClassWriter.DOUBLE:
+                return new Double(Double.longBitsToDouble(readLong(index)));
+            case ClassWriter.CLASS:
+                return Type.getObjectType(readUTF8(index, buf));
+            case ClassWriter.STR:
+                return readUTF8(index, buf);
+            case ClassWriter.MTYPE:
+                return Type.getMethodType(readUTF8(index, buf));
+
+            //case ClassWriter.HANDLE_BASE + [1..9]:
+            default: {
+                int tag = readByte(index);
+                int[] items = this.items;
+                int cpIndex = items[readUnsignedShort(index + 1)];
+                String owner = readClass(cpIndex, buf);
+                cpIndex = items[readUnsignedShort(cpIndex + 2)];
+                String name = readUTF8(cpIndex, buf);
+                String desc = readUTF8(cpIndex + 2, buf);
+                return new Handle(tag, owner, name, desc);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,306 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this class must be called
+ * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
+ * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class ClassVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The class visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected ClassVisitor cv;
+
+    /**
+     * Constructs a new {@link ClassVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public ClassVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link ClassVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param cv the class visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public ClassVisitor(final int api, final ClassVisitor cv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.cv = cv;
+    }
+
+    /**
+     * Visits the header of the class.
+     *
+     * @param version the class version.
+     * @param access the class's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the class is deprecated.
+     * @param name the internal name of the class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param signature the signature of this class. May be <tt>null</tt> if
+     *        the class is not a generic one, and does not extend or implement
+     *        generic classes or interfaces.
+     * @param superName the internal of name of the super class (see
+     *        {@link Type#getInternalName() getInternalName}). For interfaces,
+     *        the super class is {@link Object}. May be <tt>null</tt>, but
+     *        only for the {@link Object} class.
+     * @param interfaces the internal names of the class's interfaces (see
+     *        {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     */
+    public void visit(
+        int version,
+        int access,
+        String name,
+        String signature,
+        String superName,
+        String[] interfaces)
+    {
+        if (cv != null) {
+            cv.visit(version, access, name, signature, superName, interfaces);
+        }
+    }
+
+    /**
+     * Visits the source of the class.
+     *
+     * @param source the name of the source file from which the class was
+     *        compiled. May be <tt>null</tt>.
+     * @param debug additional debug information to compute the correspondance
+     *        between source and compiled elements of the class. May be
+     *        <tt>null</tt>.
+     */
+    public void visitSource(String source, String debug) {
+        if (cv != null) {
+            cv.visitSource(source, debug);
+        }
+    }
+
+    /**
+     * Visits the enclosing class of the class. This method must be called only
+     * if the class has an enclosing class.
+     *
+     * @param owner internal name of the enclosing class of the class.
+     * @param name the name of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     * @param desc the descriptor of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     */
+    public void visitOuterClass(String owner, String name, String desc) {
+        if (cv != null)  {
+            cv.visitOuterClass(owner, name, desc);
+        }
+    }
+
+    /**
+     * Visits an annotation of the class.
+     *
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (cv != null) {
+            return cv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a non standard attribute of the class.
+     *
+     * @param attr an attribute.
+     */
+    public void visitAttribute(Attribute attr) {
+        if (cv != null) {
+            cv.visitAttribute(attr);
+        }
+    }
+
+    /**
+     * Visits information about an inner class. This inner class is not
+     * necessarily a member of the class being visited.
+     *
+     * @param name the internal name of an inner class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param outerName the internal name of the class to which the inner class
+     *        belongs (see {@link Type#getInternalName() getInternalName}). May
+     *        be <tt>null</tt> for not member classes.
+     * @param innerName the (simple) name of the inner class inside its
+     *        enclosing class. May be <tt>null</tt> for anonymous inner
+     *        classes.
+     * @param access the access flags of the inner class as originally declared
+     *        in the enclosing class.
+     */
+    public void visitInnerClass(
+        String name,
+        String outerName,
+        String innerName,
+        int access)
+    {
+        if (cv != null) {
+            cv.visitInnerClass(name, outerName, innerName, access);
+        }
+    }
+
+    /**
+     * Visits a field of the class.
+     *
+     * @param access the field's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the field is synthetic and/or
+     *        deprecated.
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type Type}).
+     * @param signature the field's signature. May be <tt>null</tt> if the
+     *        field's type does not use generic types.
+     * @param value the field's initial value. This parameter, which may be
+     *        <tt>null</tt> if the field does not have an initial value, must
+     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *        {@link Double} or a {@link String} (for <tt>int</tt>,
+     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+     *        respectively). <i>This parameter is only used for static fields</i>.
+     *        Its value is ignored for non static fields, which must be
+     *        initialized through bytecode instructions in constructors or
+     *        methods.
+     * @return a visitor to visit field annotations and attributes, or
+     *         <tt>null</tt> if this class visitor is not interested in
+     *         visiting these annotations and attributes.
+     */
+    public FieldVisitor visitField(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        Object value)
+    {
+        if (cv != null) {
+            return cv.visitField(access, name, desc, signature, value);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a method of the class. This method <i>must</i> return a new
+     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
+     * called, i.e., it should not return a previously returned visitor.
+     *
+     * @param access the method's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the method is synthetic and/or
+     *        deprecated.
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     * @param signature the method's signature. May be <tt>null</tt> if the
+     *        method parameters, return type and exceptions do not use generic
+     *        types.
+     * @param exceptions the internal names of the method's exception classes
+     *        (see {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     * @return an object to visit the byte code of the method, or <tt>null</tt>
+     *         if this class visitor is not interested in visiting the code of
+     *         this method.
+     */
+    public MethodVisitor visitMethod(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        String[] exceptions)
+    {
+        if (cv != null) {
+            return cv.visitMethod(access, name, desc, signature, exceptions);
+        }
+        return null;
+    }
+
+    /**
+     * Visits the end of the class. This method, which is the last one to be
+     * called, is used to inform the visitor that all the fields and methods of
+     * the class have been visited.
+     */
+    public void visitEnd() {
+        if (cv != null) {
+            cv.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,1701 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassWriter extends ClassVisitor {
+
+    /**
+     * Flag to automatically compute the maximum stack size and the maximum
+     * number of local variables of methods. If this flag is set, then the
+     * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
+     * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
+     * method will be ignored, and computed automatically from the signature and
+     * the bytecode of each method.
+     *
+     * @see #ClassWriter(int)
+     */
+    public static final int COMPUTE_MAXS = 1;
+
+    /**
+     * Flag to automatically compute the stack map frames of methods from
+     * scratch. If this flag is set, then the calls to the
+     * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
+     * frames are recomputed from the methods bytecode. The arguments of the
+     * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+     * recomputed from the bytecode. In other words, computeFrames implies
+     * computeMaxs.
+     *
+     * @see #ClassWriter(int)
+     */
+    public static final int COMPUTE_FRAMES = 2;
+
+    /**
+     * Pseudo access flag to distinguish between the synthetic attribute and
+     * the synthetic access flag.
+     */
+    static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
+
+    /**
+     * The type of instructions without any argument.
+     */
+    static final int NOARG_INSN = 0;
+
+    /**
+     * The type of instructions with an signed byte argument.
+     */
+    static final int SBYTE_INSN = 1;
+
+    /**
+     * The type of instructions with an signed short argument.
+     */
+    static final int SHORT_INSN = 2;
+
+    /**
+     * The type of instructions with a local variable index argument.
+     */
+    static final int VAR_INSN = 3;
+
+    /**
+     * The type of instructions with an implicit local variable index argument.
+     */
+    static final int IMPLVAR_INSN = 4;
+
+    /**
+     * The type of instructions with a type descriptor argument.
+     */
+    static final int TYPE_INSN = 5;
+
+    /**
+     * The type of field and method invocations instructions.
+     */
+    static final int FIELDORMETH_INSN = 6;
+
+    /**
+     * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
+     */
+    static final int ITFMETH_INSN = 7;
+
+    /**
+     * The type of the INVOKEDYNAMIC instruction.
+     */
+    static final int INDYMETH_INSN = 8;
+
+    /**
+     * The type of instructions with a 2 bytes bytecode offset label.
+     */
+    static final int LABEL_INSN = 9;
+
+    /**
+     * The type of instructions with a 4 bytes bytecode offset label.
+     */
+    static final int LABELW_INSN = 10;
+
+    /**
+     * The type of the LDC instruction.
+     */
+    static final int LDC_INSN = 11;
+
+    /**
+     * The type of the LDC_W and LDC2_W instructions.
+     */
+    static final int LDCW_INSN = 12;
+
+    /**
+     * The type of the IINC instruction.
+     */
+    static final int IINC_INSN = 13;
+
+    /**
+     * The type of the TABLESWITCH instruction.
+     */
+    static final int TABL_INSN = 14;
+
+    /**
+     * The type of the LOOKUPSWITCH instruction.
+     */
+    static final int LOOK_INSN = 15;
+
+    /**
+     * The type of the MULTIANEWARRAY instruction.
+     */
+    static final int MANA_INSN = 16;
+
+    /**
+     * The type of the WIDE instruction.
+     */
+    static final int WIDE_INSN = 17;
+
+    /**
+     * The instruction types of all JVM opcodes.
+     */
+    static final byte[] TYPE;
+
+    /**
+     * The type of CONSTANT_Class constant pool items.
+     */
+    static final int CLASS = 7;
+
+    /**
+     * The type of CONSTANT_Fieldref constant pool items.
+     */
+    static final int FIELD = 9;
+
+    /**
+     * The type of CONSTANT_Methodref constant pool items.
+     */
+    static final int METH = 10;
+
+    /**
+     * The type of CONSTANT_InterfaceMethodref constant pool items.
+     */
+    static final int IMETH = 11;
+
+    /**
+     * The type of CONSTANT_String constant pool items.
+     */
+    static final int STR = 8;
+
+    /**
+     * The type of CONSTANT_Integer constant pool items.
+     */
+    static final int INT = 3;
+
+    /**
+     * The type of CONSTANT_Float constant pool items.
+     */
+    static final int FLOAT = 4;
+
+    /**
+     * The type of CONSTANT_Long constant pool items.
+     */
+    static final int LONG = 5;
+
+    /**
+     * The type of CONSTANT_Double constant pool items.
+     */
+    static final int DOUBLE = 6;
+
+    /**
+     * The type of CONSTANT_NameAndType constant pool items.
+     */
+    static final int NAME_TYPE = 12;
+
+    /**
+     * The type of CONSTANT_Utf8 constant pool items.
+     */
+    static final int UTF8 = 1;
+
+    /**
+     * The type of CONSTANT_MethodType constant pool items.
+     */
+    static final int MTYPE = 16;
+
+    /**
+     * The type of CONSTANT_MethodHandle constant pool items.
+     */
+    static final int HANDLE = 15;
+
+    /**
+     * The type of CONSTANT_InvokeDynamic constant pool items.
+     */
+    static final int INDY = 18;
+
+    /**
+     * The base value for all CONSTANT_MethodHandle constant pool items.
+     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
+     * 9 different items.
+     */
+    static final int HANDLE_BASE = 20;
+
+    /**
+     * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+     * instead of the constant pool, in order to avoid clashes with normal
+     * constant pool items in the ClassWriter constant pool's hash table.
+     */
+    static final int TYPE_NORMAL = 30;
+
+    /**
+     * Uninitialized type Item stored in the ClassWriter
+     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+     * avoid clashes with normal constant pool items in the ClassWriter constant
+     * pool's hash table.
+     */
+    static final int TYPE_UNINIT = 31;
+
+    /**
+     * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+     * instead of the constant pool, in order to avoid clashes with normal
+     * constant pool items in the ClassWriter constant pool's hash table.
+     */
+    static final int TYPE_MERGED = 32;
+
+    /**
+     * The type of BootstrapMethods items. These items are stored in a
+     * special class attribute named BootstrapMethods and
+     * not in the constant pool.
+     */
+    static final int BSM = 33;
+
+    /**
+     * The class reader from which this class writer was constructed, if any.
+     */
+    ClassReader cr;
+
+    /**
+     * Minor and major version numbers of the class to be generated.
+     */
+    int version;
+
+    /**
+     * Index of the next item to be added in the constant pool.
+     */
+    int index;
+
+    /**
+     * The constant pool of this class.
+     */
+    final ByteVector pool;
+
+    /**
+     * The constant pool's hash table data.
+     */
+    Item[] items;
+
+    /**
+     * The threshold of the constant pool's hash table.
+     */
+    int threshold;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key2;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key3;
+
+    /**
+     * A reusable key used to look for items in the {@link #items} hash table.
+     */
+    final Item key4;
+
+    /**
+     * A type table used to temporarily store internal names that will not
+     * necessarily be stored in the constant pool. This type table is used by
+     * the control flow and data flow analysis algorithm used to compute stack
+     * map frames from scratch. This array associates to each index <tt>i</tt>
+     * the Item whose index is <tt>i</tt>. All Item objects stored in this
+     * array are also stored in the {@link #items} hash table. These two arrays
+     * allow to retrieve an Item from its index or, conversely, to get the index
+     * of an Item from its value. Each Item stores an internal name in its
+     * {@link Item#strVal1} field.
+     */
+    Item[] typeTable;
+
+    /**
+     * Number of elements in the {@link #typeTable} array.
+     */
+    private short typeCount;
+
+    /**
+     * The access flags of this class.
+     */
+    private int access;
+
+    /**
+     * The constant pool item that contains the internal name of this class.
+     */
+    private int name;
+
+    /**
+     * The internal name of this class.
+     */
+    String thisName;
+
+    /**
+     * The constant pool item that contains the signature of this class.
+     */
+    private int signature;
+
+    /**
+     * The constant pool item that contains the internal name of the super class
+     * of this class.
+     */
+    private int superName;
+
+    /**
+     * Number of interfaces implemented or extended by this class or interface.
+     */
+    private int interfaceCount;
+
+    /**
+     * The interfaces implemented or extended by this class or interface. More
+     * precisely, this array contains the indexes of the constant pool items
+     * that contain the internal names of these interfaces.
+     */
+    private int[] interfaces;
+
+    /**
+     * The index of the constant pool item that contains the name of the source
+     * file from which this class was compiled.
+     */
+    private int sourceFile;
+
+    /**
+     * The SourceDebug attribute of this class.
+     */
+    private ByteVector sourceDebug;
+
+    /**
+     * The constant pool item that contains the name of the enclosing class of
+     * this class.
+     */
+    private int enclosingMethodOwner;
+
+    /**
+     * The constant pool item that contains the name and descriptor of the
+     * enclosing method of this class.
+     */
+    private int enclosingMethod;
+
+    /**
+     * The runtime visible annotations of this class.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this class.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this class.
+     */
+    private Attribute attrs;
+
+    /**
+     * The number of entries in the InnerClasses attribute.
+     */
+    private int innerClassesCount;
+
+    /**
+     * The InnerClasses attribute.
+     */
+    private ByteVector innerClasses;
+
+    /**
+     * The number of entries in the BootstrapMethods attribute.
+     */
+    int bootstrapMethodsCount;
+
+    /**
+     * The BootstrapMethods attribute.
+     */
+    ByteVector bootstrapMethods;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#fv} field. This field stores the first element of
+     * this list.
+     */
+    FieldWriter firstField;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#fv} field. This field stores the last element of
+     * this list.
+     */
+    FieldWriter lastField;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#mv} field. This field stores the first element of
+     * this list.
+     */
+    MethodWriter firstMethod;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#mv} field. This field stores the last element of
+     * this list.
+     */
+    MethodWriter lastMethod;
+
+    /**
+     * <tt>true</tt> if the maximum stack size and number of local variables
+     * must be automatically computed.
+     */
+    private final boolean computeMaxs;
+
+    /**
+     * <tt>true</tt> if the stack map frames must be recomputed from scratch.
+     */
+    private final boolean computeFrames;
+
+    /**
+     * <tt>true</tt> if the stack map tables of this class are invalid. The
+     * {@link MethodWriter#resizeInstructions} method cannot transform existing
+     * stack map tables, and so produces potentially invalid classes when it is
+     * executed. In this case the class is reread and rewritten with the
+     * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
+     * stack map tables when this option is used).
+     */
+    boolean invalidFrames;
+
+    // ------------------------------------------------------------------------
+    // Static initializer
+    // ------------------------------------------------------------------------
+
+    /**
+     * Computes the instruction types of JVM opcodes.
+     */
+    static {
+        int i;
+        byte[] b = new byte[220];
+        String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+                + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+                + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+                + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+        for (i = 0; i < b.length; ++i) {
+            b[i] = (byte) (s.charAt(i) - 'A');
+        }
+        TYPE = b;
+
+        // code to generate the above string
+        //
+        // // SBYTE_INSN instructions
+        // b[Constants.NEWARRAY] = SBYTE_INSN;
+        // b[Constants.BIPUSH] = SBYTE_INSN;
+        //
+        // // SHORT_INSN instructions
+        // b[Constants.SIPUSH] = SHORT_INSN;
+        //
+        // // (IMPL)VAR_INSN instructions
+        // b[Constants.RET] = VAR_INSN;
+        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        //
+        // // TYPE_INSN instructions
+        // b[Constants.NEW] = TYPE_INSN;
+        // b[Constants.ANEWARRAY] = TYPE_INSN;
+        // b[Constants.CHECKCAST] = TYPE_INSN;
+        // b[Constants.INSTANCEOF] = TYPE_INSN;
+        //
+        // // (Set)FIELDORMETH_INSN instructions
+        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+        // b[i] = FIELDORMETH_INSN;
+        // }
+        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+        // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
+        //
+        // // LABEL(W)_INSN instructions
+        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        // b[Constants.IFNULL] = LABEL_INSN;
+        // b[Constants.IFNONNULL] = LABEL_INSN;
+        // b[200] = LABELW_INSN; // GOTO_W
+        // b[201] = LABELW_INSN; // JSR_W
+        // // temporary opcodes used internally by ASM - see Label and
+        // MethodWriter
+        // for (i = 202; i < 220; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        //
+        // // LDC(_W) instructions
+        // b[Constants.LDC] = LDC_INSN;
+        // b[19] = LDCW_INSN; // LDC_W
+        // b[20] = LDCW_INSN; // LDC2_W
+        //
+        // // special instructions
+        // b[Constants.IINC] = IINC_INSN;
+        // b[Constants.TABLESWITCH] = TABL_INSN;
+        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+        // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+        // b[196] = WIDE_INSN; // WIDE
+        //
+        // for (i = 0; i < b.length; ++i) {
+        // System.err.print((char)('A' + b[i]));
+        // }
+        // System.err.println();
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassWriter} object.
+     *
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     */
+    public ClassWriter(final int flags) {
+        super(Opcodes.ASM4);
+        index = 1;
+        pool = new ByteVector();
+        items = new Item[256];
+        threshold = (int) (0.75d * items.length);
+        key = new Item();
+        key2 = new Item();
+        key3 = new Item();
+        key4 = new Item();
+        this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
+        this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+    }
+
+    /**
+     * Constructs a new {@link ClassWriter} object and enables optimizations for
+     * "mostly add" bytecode transformations. These optimizations are the
+     * following:
+     *
+     * <ul> <li>The constant pool from the original class is copied as is in the
+     * new class, which saves time. New constant pool entries will be added at
+     * the end if necessary, but unused constant pool entries <i>won't be
+     * removed</i>.</li> <li>Methods that are not transformed are copied as is
+     * in the new class, directly from the original class bytecode (i.e. without
+     * emitting visit events for all the method instructions), which saves a
+     * <i>lot</i> of time. Untransformed methods are detected by the fact that
+     * the {@link ClassReader} receives {@link MethodVisitor} objects that come
+     * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+     * instance).</li> </ul>
+     *
+     * @param classReader the {@link ClassReader} used to read the original
+     *        class. It will be used to copy the entire constant pool from the
+     *        original class and also to copy other fragments of original
+     *        bytecode where applicable.
+     * @param flags option flags that can be used to modify the default behavior
+     *        of this class. <i>These option flags do not affect methods that
+     *        are copied as is in the new class. This means that the maximum
+     *        stack size nor the stack frames will be computed for these
+     *        methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     */
+    public ClassWriter(final ClassReader classReader, final int flags) {
+        this(flags);
+        classReader.copyPool(this);
+        this.cr = classReader;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor abstract class
+    // ------------------------------------------------------------------------
+
+    @Override
+    public final void visit(
+        final int version,
+        final int access,
+        final String name,
+        final String signature,
+        final String superName,
+        final String[] interfaces)
+    {
+        this.version = version;
+        this.access = access;
+        this.name = newClass(name);
+        thisName = name;
+        if (ClassReader.SIGNATURES && signature != null) {
+            this.signature = newUTF8(signature);
+        }
+        this.superName = superName == null ? 0 : newClass(superName);
+        if (interfaces != null && interfaces.length > 0) {
+            interfaceCount = interfaces.length;
+            this.interfaces = new int[interfaceCount];
+            for (int i = 0; i < interfaceCount; ++i) {
+                this.interfaces[i] = newClass(interfaces[i]);
+            }
+        }
+    }
+
+    @Override
+    public final void visitSource(final String file, final String debug) {
+        if (file != null) {
+            sourceFile = newUTF8(file);
+        }
+        if (debug != null) {
+            sourceDebug = new ByteVector().putUTF8(debug);
+        }
+    }
+
+    @Override
+    public final void visitOuterClass(
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        enclosingMethodOwner = newClass(owner);
+        if (name != null && desc != null) {
+            enclosingMethod = newNameType(name, desc);
+        }
+    }
+
+    @Override
+    public final AnnotationVisitor visitAnnotation(
+        final String desc,
+        final boolean visible)
+    {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort(newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
+        if (visible) {
+            aw.next = anns;
+            anns = aw;
+        } else {
+            aw.next = ianns;
+            ianns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public final void visitAttribute(final Attribute attr) {
+        attr.next = attrs;
+        attrs = attr;
+    }
+
+    @Override
+    public final void visitInnerClass(
+        final String name,
+        final String outerName,
+        final String innerName,
+        final int access)
+    {
+        if (innerClasses == null) {
+            innerClasses = new ByteVector();
+        }
+        ++innerClassesCount;
+        innerClasses.putShort(name == null ? 0 : newClass(name));
+        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+        innerClasses.putShort(access);
+    }
+
+    @Override
+    public final FieldVisitor visitField(
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final Object value)
+    {
+        return new FieldWriter(this, access, name, desc, signature, value);
+    }
+
+    @Override
+    public final MethodVisitor visitMethod(
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final String[] exceptions)
+    {
+        return new MethodWriter(this,
+                access,
+                name,
+                desc,
+                signature,
+                exceptions,
+                computeMaxs,
+                computeFrames);
+    }
+
+    @Override
+    public final void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Other public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the bytecode of the class that was build with this class writer.
+     *
+     * @return the bytecode of the class that was build with this class writer.
+     */
+    public byte[] toByteArray() {
+        if (index > Short.MAX_VALUE) {
+            throw new RuntimeException("Class file too large!");
+        }
+        // computes the real size of the bytecode of this class
+        int size = 24 + 2 * interfaceCount;
+        int nbFields = 0;
+        FieldWriter fb = firstField;
+        while (fb != null) {
+            ++nbFields;
+            size += fb.getSize();
+            fb = (FieldWriter) fb.fv;
+        }
+        int nbMethods = 0;
+        MethodWriter mb = firstMethod;
+        while (mb != null) {
+            ++nbMethods;
+            size += mb.getSize();
+            mb = (MethodWriter) mb.mv;
+        }
+        int attributeCount = 0;
+        if (bootstrapMethods != null) {  // we put it as first argument in order
+                                         // to improve a bit ClassReader.copyBootstrapMethods
+            ++attributeCount;
+            size += 8 + bootstrapMethods.length;
+            newUTF8("BootstrapMethods");
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            ++attributeCount;
+            size += 8;
+            newUTF8("Signature");
+        }
+        if (sourceFile != 0) {
+            ++attributeCount;
+            size += 8;
+            newUTF8("SourceFile");
+        }
+        if (sourceDebug != null) {
+            ++attributeCount;
+            size += sourceDebug.length + 4;
+            newUTF8("SourceDebugExtension");
+        }
+        if (enclosingMethodOwner != 0) {
+            ++attributeCount;
+            size += 10;
+            newUTF8("EnclosingMethod");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            ++attributeCount;
+            size += 6;
+            newUTF8("Deprecated");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            ++attributeCount;
+            size += 6;
+            newUTF8("Synthetic");
+        }
+        if (innerClasses != null) {
+            ++attributeCount;
+            size += 8 + innerClasses.length;
+            newUTF8("InnerClasses");
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            ++attributeCount;
+            size += 8 + anns.getSize();
+            newUTF8("RuntimeVisibleAnnotations");
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            ++attributeCount;
+            size += 8 + ianns.getSize();
+            newUTF8("RuntimeInvisibleAnnotations");
+        }
+        if (attrs != null) {
+            attributeCount += attrs.getCount();
+            size += attrs.getSize(this, null, 0, -1, -1);
+        }
+        size += pool.length;
+        // allocates a byte vector of this size, in order to avoid unnecessary
+        // arraycopy operations in the ByteVector.enlarge() method
+        ByteVector out = new ByteVector(size);
+        out.putInt(0xCAFEBABE).putInt(version);
+        out.putShort(index).putByteArray(pool.data, 0, pool.length);
+        int mask = Opcodes.ACC_DEPRECATED
+                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        out.putShort(access & ~mask).putShort(name).putShort(superName);
+        out.putShort(interfaceCount);
+        for (int i = 0; i < interfaceCount; ++i) {
+            out.putShort(interfaces[i]);
+        }
+        out.putShort(nbFields);
+        fb = firstField;
+        while (fb != null) {
+            fb.put(out);
+            fb = (FieldWriter) fb.fv;
+        }
+        out.putShort(nbMethods);
+        mb = firstMethod;
+        while (mb != null) {
+            mb.put(out);
+            mb = (MethodWriter) mb.mv;
+        }
+        out.putShort(attributeCount);
+        if (bootstrapMethods != null) {   // should be the first class attribute ?
+            out.putShort(newUTF8("BootstrapMethods"));
+            out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+            out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
+        }
+        if (ClassReader.SIGNATURES && signature != 0) {
+            out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
+        }
+        if (sourceFile != 0) {
+            out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
+        }
+        if (sourceDebug != null) {
+            int len = sourceDebug.length - 2;
+            out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
+            out.putByteArray(sourceDebug.data, 2, len);
+        }
+        if (enclosingMethodOwner != 0) {
+            out.putShort(newUTF8("EnclosingMethod")).putInt(4);
+            out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            out.putShort(newUTF8("Deprecated")).putInt(0);
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0
+                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+        {
+            out.putShort(newUTF8("Synthetic")).putInt(0);
+        }
+        if (innerClasses != null) {
+            out.putShort(newUTF8("InnerClasses"));
+            out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
+            out.putByteArray(innerClasses.data, 0, innerClasses.length);
+        }
+        if (ClassReader.ANNOTATIONS && anns != null) {
+            out.putShort(newUTF8("RuntimeVisibleAnnotations"));
+            anns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && ianns != null) {
+            out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
+            ianns.put(out);
+        }
+        if (attrs != null) {
+            attrs.put(this, null, 0, -1, -1, out);
+        }
+        if (invalidFrames) {
+            ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+            new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
+            return cw.toByteArray();
+        }
+        return out.data;
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: constant pool management
+    // ------------------------------------------------------------------------
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     *
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double}, a {@link String} or a
+     *        {@link Type}.
+     * @return a new or already existing constant item with the given value.
+     */
+    Item newConstItem(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Byte) {
+            int val = ((Byte) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Character) {
+            int val = ((Character) cst).charValue();
+            return newInteger(val);
+        } else if (cst instanceof Short) {
+            int val = ((Short) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Boolean) {
+            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+            return newInteger(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            return newFloat(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            return newLong(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            return newDouble(val);
+        } else if (cst instanceof String) {
+            return newString((String) cst);
+        } else if (cst instanceof Type) {
+            Type t = (Type) cst;
+            int s = t.getSort();
+            if (s == Type.ARRAY) {
+                return newClassItem(t.getDescriptor());
+            } else if (s == Type.OBJECT) {
+                return newClassItem(t.getInternalName());
+            } else { // s == Type.METHOD
+                return newMethodTypeItem(t.getDescriptor());
+            }
+        } else if (cst instanceof Handle) {
+            Handle h = (Handle) cst;
+            return newHandleItem(h.tag, h.owner, h.name, h.desc);
+        } else {
+            throw new IllegalArgumentException("value " + cst);
+        }
+    }
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double} or a {@link String}.
+     * @return the index of a new or already existing constant item with the
+     *         given value.
+     */
+    public int newConst(final Object cst) {
+        return newConstItem(cst).index;
+    }
+
+    /**
+     * Adds an UTF8 string to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param value the String value.
+     * @return the index of a new or already existing UTF8 item.
+     */
+    public int newUTF8(final String value) {
+        key.set(UTF8, value, null, null);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(UTF8).putUTF8(value);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param value the internal name of the class.
+     * @return a new or already existing class reference item.
+     */
+    Item newClassItem(final String value) {
+        key2.set(CLASS, value, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(CLASS, newUTF8(value));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param value the internal name of the class.
+     * @return the index of a new or already existing class reference item.
+     */
+    public int newClass(final String value) {
+        return newClassItem(value).index;
+    }
+
+    /**
+     * Adds a method type reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param methodDesc method descriptor of the method type.
+     * @return a new or already existing method type reference item.
+     */
+    Item newMethodTypeItem(final String methodDesc) {
+        key2.set(MTYPE, methodDesc, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(MTYPE, newUTF8(methodDesc));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a method type reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param methodDesc method descriptor of the method type.
+     * @return the index of a new or already existing method type reference
+     *         item.
+     */
+    public int newMethodType(final String methodDesc) {
+        return newMethodTypeItem(methodDesc).index;
+    }
+
+    /**
+     * Adds a handle to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     *
+     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *        {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner the internal name of the field or method owner class.
+     * @param name the name of the field or method.
+     * @param desc the descriptor of the field or method.
+     * @return a new or an already existing method type reference item.
+     */
+    Item newHandleItem(
+        final int tag,
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        key4.set(HANDLE_BASE + tag, owner, name, desc);
+        Item result = get(key4);
+        if (result == null) {
+            if (tag <= Opcodes.H_PUTSTATIC) {
+                put112(HANDLE, tag, newField(owner, name, desc));
+            } else {
+                put112(HANDLE, tag, newMethod(owner,
+                        name,
+                        desc,
+                        tag == Opcodes.H_INVOKEINTERFACE));
+            }
+            result = new Item(index++, key4);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a handle to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *        {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner the internal name of the field or method owner class.
+     * @param name the name of the field or method.
+     * @param desc the descriptor of the field or method.
+     * @return the index of a new or already existing method type reference
+     *         item.
+     */
+    public int newHandle(
+        final int tag,
+        final String owner,
+        final String name,
+        final String desc)
+    {
+        return newHandleItem(tag, owner, name, desc).index;
+    }
+
+    /**
+     * Adds an invokedynamic reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param name name of the invoked method.
+     * @param desc descriptor of the invoke method.
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments.
+     *
+     * @return a new or an already existing invokedynamic type reference item.
+     */
+    Item newInvokeDynamicItem(
+        final String name,
+        final String desc,
+        final Handle bsm,
+        final Object... bsmArgs)
+    {
+        // cache for performance
+        ByteVector bootstrapMethods = this.bootstrapMethods;
+        if (bootstrapMethods == null) {
+            bootstrapMethods = this.bootstrapMethods = new ByteVector();
+        }
+
+        int position = bootstrapMethods.length; // record current position
+
+        int hashCode = bsm.hashCode();
+        bootstrapMethods.putShort(newHandle(bsm.tag,
+                bsm.owner,
+                bsm.name,
+                bsm.desc));
+
+        int argsLength = bsmArgs.length;
+        bootstrapMethods.putShort(argsLength);
+
+        for (int i = 0; i < argsLength; i++) {
+            Object bsmArg = bsmArgs[i];
+            hashCode ^= bsmArg.hashCode();
+            bootstrapMethods.putShort(newConst(bsmArg));
+        }
+
+        byte[] data = bootstrapMethods.data;
+        int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
+        hashCode &= 0x7FFFFFFF;
+        Item result = items[hashCode % items.length];
+        loop: while (result != null) {
+            if (result.type != BSM || result.hashCode != hashCode) {
+                result = result.next;
+                continue;
+            }
+
+            // because the data encode the size of the argument
+            // we don't need to test if these size are equals
+            int resultPosition = result.intVal;
+            for (int p = 0; p < length; p++) {
+                if (data[position + p] != data[resultPosition + p]) {
+                    result = result.next;
+                    continue loop;
+                }
+            }
+            break;
+        }
+
+        int bootstrapMethodIndex;
+        if (result != null) {
+            bootstrapMethodIndex = result.index;
+            bootstrapMethods.length = position; // revert to old position
+        } else {
+            bootstrapMethodIndex = bootstrapMethodsCount++;
+            result = new Item(bootstrapMethodIndex);
+            result.set(position, hashCode);
+            put(result);
+        }
+
+        // now, create the InvokeDynamic constant
+        key3.set(name, desc, bootstrapMethodIndex);
+        result = get(key3);
+        if (result == null) {
+            put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds an invokedynamic reference to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param name name of the invoked method.
+     * @param desc descriptor of the invoke method.
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments.
+     *
+     * @return the index of a new or already existing invokedynamic
+     *         reference item.
+     */
+    public int newInvokeDynamic(
+        final String name,
+        final String desc,
+        final Handle bsm,
+        final Object... bsmArgs)
+    {
+        return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
+    }
+
+    /**
+     * Adds a field reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     *
+     * @param owner the internal name of the field's owner class.
+     * @param name the field's name.
+     * @param desc the field's descriptor.
+     * @return a new or already existing field reference item.
+     */
+    Item newFieldItem(final String owner, final String name, final String desc)
+    {
+        key3.set(FIELD, owner, name, desc);
+        Item result = get(key3);
+        if (result == null) {
+            put122(FIELD, newClass(owner), newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a field reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param owner the internal name of the field's owner class.
+     * @param name the field's name.
+     * @param desc the field's descriptor.
+     * @return the index of a new or already existing field reference item.
+     */
+    public int newField(final String owner, final String name, final String desc)
+    {
+        return newFieldItem(owner, name, desc).index;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     *
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return a new or already existing method reference item.
+     */
+    Item newMethodItem(
+        final String owner,
+        final String name,
+        final String desc,
+        final boolean itf)
+    {
+        int type = itf ? IMETH : METH;
+        key3.set(type, owner, name, desc);
+        Item result = get(key3);
+        if (result == null) {
+            put122(type, newClass(owner), newNameType(name, desc));
+            result = new Item(index++, key3);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     *
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return the index of a new or already existing method reference item.
+     */
+    public int newMethod(
+        final String owner,
+        final String name,
+        final String desc,
+        final boolean itf)
+    {
+        return newMethodItem(owner, name, desc, itf).index;
+    }
+
+    /**
+     * Adds an integer to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item.
+     *
+     * @param value the int value.
+     * @return a new or already existing int item.
+     */
+    Item newInteger(final int value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(INT).putInt(value);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a float to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the float value.
+     * @return a new or already existing float item.
+     */
+    Item newFloat(final float value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(FLOAT).putInt(key.intVal);
+            result = new Item(index++, key);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a long to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the long value.
+     * @return a new or already existing long item.
+     */
+    Item newLong(final long value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(LONG).putLong(value);
+            result = new Item(index, key);
+            index += 2;
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a double to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the double value.
+     * @return a new or already existing double item.
+     */
+    Item newDouble(final double value) {
+        key.set(value);
+        Item result = get(key);
+        if (result == null) {
+            pool.putByte(DOUBLE).putLong(key.longVal);
+            result = new Item(index, key);
+            index += 2;
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a string to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     *
+     * @param value the String value.
+     * @return a new or already existing string item.
+     */
+    private Item newString(final String value) {
+        key2.set(STR, value, null, null);
+        Item result = get(key2);
+        if (result == null) {
+            pool.put12(STR, newUTF8(value));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds a name and type to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     *
+     * @param name a name.
+     * @param desc a type descriptor.
+     * @return the index of a new or already existing name and type item.
+     */
+    public int newNameType(final String name, final String desc) {
+        return newNameTypeItem(name, desc).index;
+    }
+
+    /**
+     * Adds a name and type to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item.
+     *
+     * @param name a name.
+     * @param desc a type descriptor.
+     * @return a new or already existing name and type item.
+     */
+    Item newNameTypeItem(final String name, final String desc) {
+        key2.set(NAME_TYPE, name, desc, null);
+        Item result = get(key2);
+        if (result == null) {
+            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
+            result = new Item(index++, key2);
+            put(result);
+        }
+        return result;
+    }
+
+    /**
+     * Adds the given internal name to {@link #typeTable} and returns its index.
+     * Does nothing if the type table already contains this internal name.
+     *
+     * @param type the internal name to be added to the type table.
+     * @return the index of this internal name in the type table.
+     */
+    int addType(final String type) {
+        key.set(TYPE_NORMAL, type, null, null);
+        Item result = get(key);
+        if (result == null) {
+            result = addType(key);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds the given "uninitialized" type to {@link #typeTable} and returns its
+     * index. This method is used for UNINITIALIZED types, made of an internal
+     * name and a bytecode offset.
+     *
+     * @param type the internal name to be added to the type table.
+     * @param offset the bytecode offset of the NEW instruction that created
+     *        this UNINITIALIZED type value.
+     * @return the index of this internal name in the type table.
+     */
+    int addUninitializedType(final String type, final int offset) {
+        key.type = TYPE_UNINIT;
+        key.intVal = offset;
+        key.strVal1 = type;
+        key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
+        Item result = get(key);
+        if (result == null) {
+            result = addType(key);
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds the given Item to {@link #typeTable}.
+     *
+     * @param item the value to be added to the type table.
+     * @return the added Item, which a new Item instance with the same value as
+     *         the given Item.
+     */
+    private Item addType(final Item item) {
+        ++typeCount;
+        Item result = new Item(typeCount, key);
+        put(result);
+        if (typeTable == null) {
+            typeTable = new Item[16];
+        }
+        if (typeCount == typeTable.length) {
+            Item[] newTable = new Item[2 * typeTable.length];
+            System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
+            typeTable = newTable;
+        }
+        typeTable[typeCount] = result;
+        return result;
+    }
+
+    /**
+     * Returns the index of the common super type of the two given types. This
+     * method calls {@link #getCommonSuperClass} and caches the result in the
+     * {@link #items} hash table to speedup future calls with the same
+     * parameters.
+     *
+     * @param type1 index of an internal name in {@link #typeTable}.
+     * @param type2 index of an internal name in {@link #typeTable}.
+     * @return the index of the common super type of the two given types.
+     */
+    int getMergedType(final int type1, final int type2) {
+        key2.type = TYPE_MERGED;
+        key2.longVal = type1 | (((long) type2) << 32);
+        key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
+        Item result = get(key2);
+        if (result == null) {
+            String t = typeTable[type1].strVal1;
+            String u = typeTable[type2].strVal1;
+            key2.intVal = addType(getCommonSuperClass(t, u));
+            result = new Item((short) 0, key2);
+            put(result);
+        }
+        return result.intVal;
+    }
+
+    /**
+     * Returns the common super type of the two given types. The default
+     * implementation of this method <i>loads<i> the two given classes and uses
+     * the java.lang.Class methods to find the common super class. It can be
+     * overridden to compute this common super type in other ways, in particular
+     * without actually loading any class, or to take into account the class
+     * that is currently being generated by this ClassWriter, which can of
+     * course not be loaded since it is under construction.
+     *
+     * @param type1 the internal name of a class.
+     * @param type2 the internal name of another class.
+     * @return the internal name of the common super class of the two given
+     *         classes.
+     */
+    protected String getCommonSuperClass(final String type1, final String type2)
+    {
+        Class<?> c, d;
+        ClassLoader classLoader = getClass().getClassLoader();
+        try {
+            c = Class.forName(type1.replace('/', '.'), false, classLoader);
+            d = Class.forName(type2.replace('/', '.'), false, classLoader);
+        } catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+        if (c.isAssignableFrom(d)) {
+            return type1;
+        }
+        if (d.isAssignableFrom(c)) {
+            return type2;
+        }
+        if (c.isInterface() || d.isInterface()) {
+            return "java/lang/Object";
+        } else {
+            do {
+                c = c.getSuperclass();
+            } while (!c.isAssignableFrom(d));
+            return c.getName().replace('.', '/');
+        }
+    }
+
+    /**
+     * Returns the constant pool's hash table item which is equal to the given
+     * item.
+     *
+     * @param key a constant pool item.
+     * @return the constant pool's hash table item which is equal to the given
+     *         item, or <tt>null</tt> if there is no such item.
+     */
+    private Item get(final Item key) {
+        Item i = items[key.hashCode % items.length];
+        while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
+            i = i.next;
+        }
+        return i;
+    }
+
+    /**
+     * Puts the given item in the constant pool's hash table. The hash table
+     * <i>must</i> not already contains this item.
+     *
+     * @param i the item to be added to the constant pool's hash table.
+     */
+    private void put(final Item i) {
+        if (index + typeCount > threshold) {
+            int ll = items.length;
+            int nl = ll * 2 + 1;
+            Item[] newItems = new Item[nl];
+            for (int l = ll - 1; l >= 0; --l) {
+                Item j = items[l];
+                while (j != null) {
+                    int index = j.hashCode % newItems.length;
+                    Item k = j.next;
+                    j.next = newItems[index];
+                    newItems[index] = j;
+                    j = k;
+                }
+            }
+            items = newItems;
+            threshold = (int) (nl * 0.75);
+        }
+        int index = i.hashCode % items.length;
+        i.next = items[index];
+        items[index] = i;
+    }
+
+    /**
+     * Puts one byte and two shorts into the constant pool.
+     *
+     * @param b a byte.
+     * @param s1 a short.
+     * @param s2 another short.
+     */
+    private void put122(final int b, final int s1, final int s2) {
+        pool.put12(b, s1).putShort(s2);
+    }
+
+    /**
+     * Puts two bytes and one short into the constant pool.
+     *
+     * @param b1 a byte.
+     * @param b2 another byte.
+     * @param s a short.
+     */
+    private void put112(final int b1, final int b2, final int s) {
+        pool.put11(b1, b2).putShort(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/Edge.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,104 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ *
+ * @author Eric Bruneton
+ */
+class Edge {
+
+    /**
+     * Denotes a normal control flow graph edge.
+     */
+    static final int NORMAL = 0;
+
+    /**
+     * Denotes a control flow graph edge corresponding to an exception handler.
+     * More precisely any {@link Edge} whose {@link #info} is strictly positive
+     * corresponds to an exception handler. The actual value of {@link #info} is
+     * the index, in the {@link ClassWriter} type table, of the exception that
+     * is catched.
+     */
+    static final int EXCEPTION = 0x7FFFFFFF;
+
+    /**
+     * Information about this control flow graph edge. If
+     * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
+     * stack size in the basic block from which this edge originates. This size
+     * is equal to the stack size at the "jump" instruction to which this edge
+     * corresponds, relatively to the stack size at the beginning of the
+     * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
+     * this field is the kind of this control flow graph edge (i.e. NORMAL or
+     * EXCEPTION).
+     */
+    int info;
+
+    /**
+     * The successor block of the basic block from which this edge originates.
+     */
+    Label successor;
+
+    /**
+     * The next edge in the list of successors of the originating basic block.
+     * See {@link Label#successors successors}.
+     */
+    Edge next;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,144 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this class must be called
+ * in the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class FieldVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The field visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected FieldVisitor fv;
+
+    /**
+     * Constructs a new {@link FieldVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public FieldVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link FieldVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param fv the field visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public FieldVisitor(final int api, final FieldVisitor fv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.fv = fv;
+    }
+
+    /**
+     * Visits an annotation of the field.
+     *
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values, or <tt>null</tt> if
+     *         this visitor is not interested in visiting this annotation.
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (fv != null) {
+            return fv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
+
+    /**
+     * Visits a non standard attribute of the field.
+     *
+     * @param attr an attribute.
+     */
+    public void visitAttribute(Attribute attr) {
+        if (fv != null) {
+            fv.visitAttribute(attr);
+        }
+    }
+
+    /**
+     * Visits the end of the field. This method, which is the last one to be
+     * called, is used to inform the visitor that all the annotations and
+     * attributes of the field have been visited.
+     */
+    public void visitEnd() {
+        if (fv != null) {
+            fv.visitEnd();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java	Tue Oct 23 09:41:52 2012 -0700
@@ -0,0 +1,300 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jdk.internal.org.objectweb.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ *
+ * @author Eric Bruneton
+ */
+final class FieldWriter extends FieldVisitor {
+
+    /**
+     * The class writer to which this field must be added.
+     */
+    private final ClassWriter cw;
+
+    /**
+     * Access flags of this field.
+     */
+    private final int access;
+
+    /**
+     * The index of the constant pool item that contains the name of this
+     * method.
+     */
+    private final int name;
+
+    /**
+     * The index of the constant pool item that contains the descriptor of this
+     * field.
+     */
+    private final int desc;
+
+    /**
+     * The index of the constant pool item that contains the signature of this
+     * field.
+     */
+    private int signature;
+
+    /**
+     * The index of the constant pool item that contains the constant value of
+     * this field.
+     */
+    private int value;
+
+    /**
+     * The runtime visible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this field. May be <tt>null</tt>.
+     */
+    private Attribute attrs;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link FieldWriter}.
+     *
+     * @param cw the class writer to which this field must be added.
+     * @param access the field's access flags (see {@link Opcodes}).
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type}).
+     * @param signature the field's signature. May be <tt>null</tt>.
+     * @param value the field's constant value. May be <tt>null</tt>.
+     */
+    FieldWriter(
+        final ClassWriter cw,
+        final int access,
+        final String name,
+        final String desc,