changeset 3141:1a6bcdf42058

Merge
author igor
date Thu, 18 Nov 2010 10:35:46 -0800
parents 720863527b90 ecab7eefb8f2
children f32734df1bdd
files src/share/classes/java/dyn/JavaMethodHandle.java src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java src/share/classes/sun/java2d/pisces/LineSink.java src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java test/java/nio/channels/AsynchronousDatagramChannel/Basic.java
diffstat 505 files changed, 29688 insertions(+), 11236 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Oct 22 14:14:54 2010 -0400
+++ b/.hgtags	Thu Nov 18 10:35:46 2010 -0800
@@ -90,3 +90,6 @@
 61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113
 e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114
 449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115
+1657ed4e1d86c8aa2028ab5a41f9da1ac4a369f8 jdk7-b116
+3e6726bbf80a4254ecd01051c8ed77ee19325e46 jdk7-b117
+b357910aa04aead2a16b6d6ff395a8df4b51d1dd jdk7-b118
--- a/make/java/java/FILES_java.gmk	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/java/java/FILES_java.gmk	Thu Nov 18 10:35:46 2010 -0800
@@ -413,6 +413,7 @@
     java/io/FilePermission.java \
     java/io/Serializable.java \
     java/io/Externalizable.java \
+    java/io/SerialCallbackContext.java \
 	java/io/Bits.java \
 	java/io/ObjectInput.java \
 	java/io/ObjectInputStream.java \
@@ -465,14 +466,11 @@
     java/security/ProtectionDomain.java \
     java/net/URLClassLoader.java \
     java/net/URLConnection.java \
+    sun/misc/BootClassLoaderHook.java \
     sun/misc/Launcher.java \
     sun/misc/MetaIndex.java \
     sun/misc/URLClassPath.java \
     sun/misc/Version.java \
-    sun/net/www/protocol/jar/Handler.java \
-    sun/net/www/protocol/jar/JarURLConnection.java \
-    sun/net/www/protocol/file/Handler.java \
-    sun/net/www/protocol/file/FileURLConnection.java \
     sun/misc/FileURLMapper.java \
     sun/misc/MessageUtils.java \
     sun/misc/GC.java \
@@ -482,6 +480,10 @@
     sun/misc/JavaIOFileDescriptorAccess.java \
     sun/misc/JavaNioAccess.java \
     sun/misc/Perf.java \
-    sun/misc/PerfCounter.java
+    sun/misc/PerfCounter.java \
+    sun/net/www/protocol/jar/Handler.java \
+    sun/net/www/protocol/jar/JarURLConnection.java \
+    sun/net/www/protocol/file/Handler.java \
+    sun/net/www/protocol/file/FileURLConnection.java
 
 FILES_java = $(JAVA_JAVA_java)
--- a/make/java/jli/Makefile	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/java/jli/Makefile	Thu Nov 18 10:35:46 2010 -0800
@@ -148,14 +148,9 @@
 #
 ifeq ($(PLATFORM), windows)
 
-STATIC_LIBRARY_DIR = $(OBJDIR)/static
-STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
-STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
+STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
 
-$(STATIC_LIBRARY_DIR): $(OBJDIR)
-	@$(MKDIR) $(STATIC_LIBRARY_DIR)
-
-$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
+$(STATIC_LIBRARY): $(FILES_o)
 	@$(prep-target)
 	$(LIBEXE) -nologo -out:$@ $(FILES_o)
 
--- a/make/java/nio/FILES_java.gmk	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/java/nio/FILES_java.gmk	Thu Nov 18 10:35:46 2010 -0800
@@ -33,7 +33,6 @@
 	java/nio/channels/AsynchronousByteChannel.java \
 	java/nio/channels/AsynchronousChannel.java \
 	java/nio/channels/AsynchronousChannelGroup.java \
-	java/nio/channels/AsynchronousDatagramChannel.java \
 	java/nio/channels/AsynchronousFileChannel.java \
 	java/nio/channels/AsynchronousServerSocketChannel.java \
 	java/nio/channels/AsynchronousSocketChannel.java \
@@ -207,7 +206,6 @@
 	sun/nio/ch/SelChImpl.java \
 	sun/nio/ch/ServerSocketAdaptor.java \
 	sun/nio/ch/ServerSocketChannelImpl.java \
-	sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
         sun/nio/ch/SinkChannelImpl.java \
 	sun/nio/ch/SocketAdaptor.java \
 	sun/nio/ch/SocketChannelImpl.java \
--- a/make/javax/sound/jsoundds/Makefile	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/javax/sound/jsoundds/Makefile	Thu Nov 18 10:35:46 2010 -0800
@@ -53,7 +53,7 @@
 #
 # Extra cc/linker flags.
 #
-LDLIBS += dsound.lib winmm.lib user32.lib
+LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib
 CPPFLAGS += \
 	-DUSE_DAUDIO=TRUE \
 	-I$(SHARE_SRC)/native/com/sun/media/sound \
--- a/make/netbeans/jmx/build.properties	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/netbeans/jmx/build.properties	Thu Nov 18 10:35:46 2010 -0800
@@ -48,8 +48,8 @@
 jar.jmx.sealed				= true
 jar.jmx.spec.title			= JSR 003, 160, 255 - JMX API
 jar.jmx.spec.version			= ${project.spec.version}
-jar.jmx.spec.vendor			= Sun Microsystems, Inc.
-jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API 
+jar.jmx.spec.vendor			= Oracle Corporation
+jar.jmx.impl.title			= JSR 003, 160, 255 - OpenJDK 7 JMX API
 jar.jmx.impl.vendor			= Project OpenJDK
 
 javadoc.options=-J-Xmx256m
--- a/make/sun/image/generic/Makefile	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/sun/image/generic/Makefile	Thu Nov 18 10:35:46 2010 -0800
@@ -69,5 +69,8 @@
             -I$(PLATFORM_SRC)/native/$(PKGDIR)/medialib 
 
 OTHER_CFLAGS += -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES
-OTHER_LDLIBS = $(LIBM) -ldl
 
+ifneq ($(PLATFORM), windows)
+	OTHER_LDLIBS = $(LIBM) -ldl
+endif
+
--- a/make/sun/javazic/tzdata/VERSION	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/sun/javazic/tzdata/VERSION	Thu Nov 18 10:35:46 2010 -0800
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2010l
+tzdata2010o
--- a/make/sun/javazic/tzdata/asia	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/sun/javazic/tzdata/asia	Thu Nov 18 10:35:46 2010 -0800
@@ -569,8 +569,8 @@
 Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
 Rule	HK	1954	only	-	Oct	31	3:30	0	-
 Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
-Rule	HK	1965	1977	-	Apr	Sun>=16	3:30	1:00	S
-Rule	HK	1965	1977	-	Oct	Sun>=16	3:30	0	-
+Rule	HK	1965	1976	-	Apr	Sun>=16	3:30	1:00	S
+Rule	HK	1965	1976	-	Oct	Sun>=16	3:30	0	-
 Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
 Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
 Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
--- a/make/sun/javazic/tzdata/australasia	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/sun/javazic/tzdata/australasia	Thu Nov 18 10:35:46 2010 -0800
@@ -306,13 +306,26 @@
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
 # </a>
 
+# From Alexander Krivenyshev (2010-10-24):
+# According to Radio Fiji and Fiji Times online, Fiji will end DST 3 
+# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
+# Here is confirmation from Government of the Republic of the Fiji Islands, 
+# Ministry of Information (fiji.gov.fj) web site:
+# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
+# </a>
+# or
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
+# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
+# </a>
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
 Rule	Fiji	2009	only	-	Nov	29	2:00	1:00	S
 Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
 Rule	Fiji	2010	only	-	Oct	24	2:00	1:00	S
-Rule	Fiji	2011	only	-	Mar	lastSun 3:00	0	-
+Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
@@ -509,11 +522,21 @@
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
 # </a>
 
+# From Raymond Hughes (2010-10-07):
+# Please see
+# <a href="http://www.mcil.gov.ws">
+# http://www.mcil.gov.ws
+# </a>,
+# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
+# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
+# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
+# backwards from 1:00am to 12:00am"
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
 			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 3
+			-11:00	1:00	WSDT	2011 Apr 3 1:00
 			-11:00	-	WST
 
 # Solomon Is
--- a/make/sun/javazic/tzdata/zone.tab	Fri Oct 22 14:14:54 2010 -0400
+++ b/make/sun/javazic/tzdata/zone.tab	Thu Nov 18 10:35:46 2010 -0800
@@ -63,7 +63,7 @@
 AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
-AQ	-7824+10654	Antarctica/Vostok	Vostok Station, S Magnetic Pole
+AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
 AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-5430+15857	Antarctica/Macquarie	Macquarie Island Station, Macquarie Island
--- a/src/share/bin/java.c	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/bin/java.c	Thu Nov 18 10:35:46 2010 -0800
@@ -355,7 +355,6 @@
 
     JavaVM *vm = 0;
     JNIEnv *env = 0;
-    jstring mainClassName;
     jclass mainClass;
     jmethodID mainID;
     jobjectArray mainArgs;
--- a/src/share/bin/parse_manifest.c	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/bin/parse_manifest.c	Thu Nov 18 10:35:46 2010 -0800
@@ -72,7 +72,7 @@
     if (entry->how == STORED) {
         *(char *)((size_t)in + entry->csize) = '\0';
         if (size_out) {
-            *size_out = entry->csize;
+            *size_out = (int)entry->csize;
         }
         return (in);
     } else if (entry->how == DEFLATED) {
@@ -103,7 +103,7 @@
             return (NULL);
         }
         if (size_out) {
-            *size_out = entry->isize;
+            *size_out = (int)entry->isize;
         }
         return (out);
     } else
@@ -317,7 +317,7 @@
          * manifest.  If so, build the entry record from the data found in
          * the header located and return success.
          */
-        if (CENNAM(p) == JLI_StrLen(file_name) &&
+        if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
           memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
             if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
                 free(buffer);
@@ -606,8 +606,5 @@
     }
     free(mp);
     close(fd);
-    if (rc == 0)
-        return (0);
-    else
-        return (-2);
+    return (rc == 0) ? 0 : -2;
 }
--- a/src/share/bin/wildcard.c	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/bin/wildcard.c	Thu Nov 18 10:35:46 2010 -0800
@@ -290,12 +290,12 @@
     char *path;
     char *p;
     for (i = 0, size = 1; i < fl->size; i++)
-        size += JLI_StrLen(fl->files[i]) + 1;
+        size += (int)JLI_StrLen(fl->files[i]) + 1;
 
     path = JLI_MemAlloc(size);
 
     for (i = 0, p = path; i < fl->size; i++) {
-        int len = JLI_StrLen(fl->files[i]);
+        int len = (int)JLI_StrLen(fl->files[i]);
         if (i > 0) *p++ = sep;
         memcpy(p, fl->files[i], len);
         p += len;
@@ -309,7 +309,7 @@
 FileList_split(const char *path, char sep)
 {
     const char *p, *q;
-    int len = JLI_StrLen(path);
+    int len = (int)JLI_StrLen(path);
     int count;
     FileList fl;
     for (count = 1, p = path; p < path + len; p++)
@@ -330,7 +330,7 @@
 static int
 isJarFileName(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len >= 4) &&
         (filename[len - 4] == '.') &&
         (equal(filename + len - 3, "jar") ||
@@ -342,8 +342,8 @@
 static char *
 wildcardConcat(const char *wildcard, const char *basename)
 {
-    int wildlen = JLI_StrLen(wildcard);
-    int baselen = JLI_StrLen(basename);
+    int wildlen = (int)JLI_StrLen(wildcard);
+    int baselen = (int)JLI_StrLen(basename);
     char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
     /* Replace the trailing '*' with basename */
     memcpy(filename, wildcard, wildlen-1);
@@ -369,7 +369,7 @@
 static int
 isWildcard(const char *filename)
 {
-    int len = JLI_StrLen(filename);
+    int len = (int)JLI_StrLen(filename);
     return (len > 0) &&
         (filename[len - 1] == '*') &&
         (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
--- a/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -253,7 +253,8 @@
             for (j = 0; j < 8; j++) {
                 if (AA[i][j] != 0) {
                     AA[i][j] = (byte)
-                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
+                        alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
+                        % 255];
                 }
             }
             for (t = 0; t < 4; t++) {
--- a/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -92,7 +92,8 @@
     }
 
     // core crypt code. OFB style, so works for both encryption and decryption
-    private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
+    private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs) {
         if (is < 0) {
             // doFinal() was called, need to reset the cipher to initial state
             init(lastKey);
--- a/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/DESedeCipher.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -31,8 +31,8 @@
 import javax.crypto.spec.*;
 
 /**
- * This class implements the DESede algorithm (DES-EDE, tripleDES) in its various
- * modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
+ * This class implements the DESede algorithm (DES-EDE, tripleDES) in
+ * its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
  * <code>CBC</code>, <code>PCBC</code>) and padding schemes
  * (<code>PKCS5Padding</code>, <code>NoPadding</code>,
  * <code>ISO10126Padding</code>).
--- a/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -190,7 +190,8 @@
             ike.initCause(e);
             throw ike;
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
@@ -300,7 +301,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.x = in.getBigInteger();
         } catch (IOException e) {
-            InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
+            InvalidKeyException ike = new InvalidKeyException(
+                "Error parsing key encoding: " + e.getMessage());
             ike.initCause(e);
             throw ike;
         }
--- a/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/DHPublicKey.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -180,7 +180,8 @@
             throw new InvalidKeyException("Private-value length too big");
 
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
@@ -281,7 +282,8 @@
             DerInputStream in = new DerInputStream(this.key);
             this.y = in.getBigInteger();
         } catch (IOException e) {
-            throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
+            throw new InvalidKeyException(
+                "Error parsing key encoding: " + e.toString());
         }
     }
 
--- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, 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
@@ -764,7 +764,8 @@
                                     cf = (CertificateFactory)cfs.get(certType);
                                 } else {
                                 // create new certificate factory
-                                    cf = CertificateFactory.getInstance(certType);
+                                    cf = CertificateFactory.getInstance(
+                                        certType);
                                 // store the certificate factory so we can
                                 // reuse it later
                                     cfs.put(certType, cf);
@@ -863,8 +864,9 @@
                     dis.readFully(actual);
                     for (int i = 0; i < computed.length; i++) {
                         if (computed[i] != actual[i]) {
-                            throw new IOException("Keystore was tampered with, or "
-                                                  + "password was incorrect");
+                            throw new IOException(
+                                "Keystore was tampered with, or "
+                                + "password was incorrect");
                         }
                     }
                 }
--- a/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -139,7 +139,8 @@
                 if (!val.getOID().equals((Object) OID_MGF1)) {
                     throw new IOException("Only MGF1 mgf is supported");
                 }
-                AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams()));
+                AlgorithmId params = AlgorithmId.parse(
+                    new DerValue(val.getEncodedParams()));
                 String mgfDigestName = convertToStandardName(params.getName());
                 if (mgfDigestName.equals("SHA-1")) {
                     mgfSpec = MGF1ParameterSpec.SHA1;
@@ -150,7 +151,8 @@
                 } else if (mgfDigestName.equals("SHA-512")) {
                     mgfSpec = MGF1ParameterSpec.SHA512;
                 } else {
-                    throw new IOException("Unrecognized message digest algorithm");
+                    throw new IOException(
+                        "Unrecognized message digest algorithm");
                 }
             } else if (data.isContextSpecific((byte) 0x02)) {
                 // pSource algid
--- a/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -121,8 +121,8 @@
         this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
     }
 
-    private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt,
-                                    int iterCount, int keyLengthInBit) {
+    private static byte[] deriveKey(final Mac prf, final byte[] password,
+            byte[] salt, int iterCount, int keyLengthInBit) {
         int keyLength = keyLengthInBit/8;
         byte[] key = new byte[keyLength];
         try {
@@ -155,8 +155,9 @@
                     if (this == obj) return true;
                     if (this.getClass() != obj.getClass()) return false;
                     SecretKey sk = (SecretKey)obj;
-                    return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) &&
-                            Arrays.equals(password, sk.getEncoded());
+                    return prf.getAlgorithm().equalsIgnoreCase(
+                        sk.getAlgorithm()) &&
+                        Arrays.equals(password, sk.getEncoded());
                 }
             };
             prf.init(macKey);
--- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -206,7 +206,8 @@
                 (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
         } catch (GeneralSecurityException gse) {
             // should never happen
-            throw new RuntimeException("SunJCE provider is not configured properly");
+            throw new RuntimeException(
+                "SunJCE provider is not configured properly");
         }
         try {
             params.init(pbeSpec);
@@ -316,7 +317,8 @@
             try {
                 paramSpec = params.getParameterSpec(PBEParameterSpec.class);
             } catch (InvalidParameterSpecException ipse) {
-                throw new InvalidAlgorithmParameterException("requires PBE parameters");
+                throw new InvalidAlgorithmParameterException(
+                    "requires PBE parameters");
             }
         }
         implInit(opmode, key, paramSpec, random);
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -423,15 +423,31 @@
 
                 /*
                  * SSL/TLS mechanisms
+                 *
+                 * These are strictly internal implementations and may
+                 * be changed at any time.  These names were chosen
+                 * because PKCS11/SunPKCS11 does not yet have TLS1.2
+                 * mechanisms, and it will cause calls to come here.
                  */
                 put("KeyGenerator.SunTlsPrf",
-                        "com.sun.crypto.provider.TlsPrfGenerator");
+                        "com.sun.crypto.provider.TlsPrfGenerator$V10");
+                put("KeyGenerator.SunTls12Prf",
+                        "com.sun.crypto.provider.TlsPrfGenerator$V12");
+
+                put("KeyGenerator.SunTlsMasterSecret",
+                    "com.sun.crypto.provider.TlsMasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
+                    "SunTlsMasterSecret");
+
+                put("KeyGenerator.SunTlsKeyMaterial",
+                    "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12KeyMaterial",
+                    "SunTlsKeyMaterial");
+
                 put("KeyGenerator.SunTlsRsaPremasterSecret",
-                        "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
-                put("KeyGenerator.SunTlsMasterSecret",
-                        "com.sun.crypto.provider.TlsMasterSecretGenerator");
-                put("KeyGenerator.SunTlsKeyMaterial",
-                        "com.sun.crypto.provider.TlsKeyMaterialGenerator");
+                    "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
+                put("Alg.Alias.KeyGenerator.SunTls12RsaPremasterSecret",
+                    "SunTlsRsaPremasterSecret");
 
                 return null;
             }
--- a/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,12 +65,14 @@
         }
         this.spec = (TlsKeyMaterialParameterSpec)params;
         if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -80,8 +82,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsKeyMaterialGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsKeyMaterialGenerator must be initialized");
         }
         try {
             return engineGenerateKey0();
@@ -99,8 +101,8 @@
         SecretKey clientMacKey = null;
         SecretKey serverMacKey = null;
         SecretKey clientCipherKey = null;
+        SecretKey serverCipherKey = null;
         IvParameterSpec clientIv = null;
-        SecretKey serverCipherKey = null;
         IvParameterSpec serverIv = null;
 
         int macLength = spec.getMacKeyLength();
@@ -109,21 +111,33 @@
         int keyLength = spec.getCipherKeyLength();
         int ivLength = spec.getIvLength();
 
-        int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength);
+        int keyBlockLen = macLength + keyLength
+            + (isExportable ? 0 : ivLength);
         keyBlockLen <<= 1;
         byte[] keyBlock = new byte[keyBlockLen];
 
-        MessageDigest md5 = MessageDigest.getInstance("MD5");
-        MessageDigest sha = MessageDigest.getInstance("SHA1");
+        // These may be used again later for exportable suite calculations.
+        MessageDigest md5 = null;
+        MessageDigest sha = null;
 
         // generate key block
-        if (protocolVersion >= 0x0301) {
-            // TLS
+        if (protocolVersion >= 0x0303) {
+            // TLS 1.2
             byte[] seed = concat(serverRandom, clientRandom);
-            keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+            keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
+                        keyBlockLen, spec.getPRFHashAlg(),
+                        spec.getPRFHashLength(), spec.getPRFBlockSize());
+        } else if (protocolVersion >= 0x0301) {
+            // TLS 1.0/1.1
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
+            byte[] seed = concat(serverRandom, clientRandom);
+            keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
                         keyBlockLen, md5, sha);
         } else {
             // SSL
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA1");
             keyBlock = new byte[keyBlockLen];
 
             byte[] tmp = new byte[20];
@@ -169,6 +183,7 @@
 
         String alg = spec.getCipherAlgorithm();
 
+        // cipher keys
         byte[] clientKeyBytes = new byte[keyLength];
         System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
         ofs += keyLength;
@@ -182,6 +197,7 @@
             clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
             serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
 
+            // IV keys if needed.
             if (ivLength != 0) {
                 tmp = new byte[ivLength];
 
@@ -194,21 +210,28 @@
                 serverIv = new IvParameterSpec(tmp);
             }
         } else {
+            // if exportable suites, calculate the alternate
             // cipher key expansion and IV generation
-            if (protocolVersion >= 0x0301) {
+            if (protocolVersion >= 0x0302) {
+                // TLS 1.1+
+                throw new RuntimeException(
+                    "Internal Error:  TLS 1.1+ should not be negotiating" +
+                    "exportable ciphersuites");
+            } else if (protocolVersion == 0x0301) {
+                // TLS 1.0
                 byte[] seed = concat(clientRandom, serverRandom);
 
-                tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
+                tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 clientCipherKey = new SecretKeySpec(tmp, alg);
 
-                tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
+                tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
                             expandedKeyLength, md5, sha);
                 serverCipherKey = new SecretKeySpec(tmp, alg);
 
                 if (ivLength != 0) {
                     tmp = new byte[ivLength];
-                    byte[] block = doPRF(null, LABEL_IV_BLOCK, seed,
+                    byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
                                 ivLength << 1, md5, sha);
                     System.arraycopy(block, 0, tmp, 0, ivLength);
                     clientIv = new IvParameterSpec(tmp);
@@ -216,6 +239,7 @@
                     serverIv = new IvParameterSpec(tmp);
                 }
             } else {
+                // SSLv3
                 tmp = new byte[expandedKeyLength];
 
                 md5.update(clientKeyBytes);
--- a/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,12 +64,14 @@
         }
         this.spec = (TlsMasterSecretParameterSpec)params;
         if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
-            throw new InvalidAlgorithmParameterException("Key format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key format must be RAW");
         }
-        protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
-        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) {
-            throw new InvalidAlgorithmParameterException
-                ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
+        protocolVersion = (spec.getMajorVersion() << 8)
+            | spec.getMinorVersion();
+        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
+            throw new InvalidAlgorithmParameterException(
+                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
         }
     }
 
@@ -79,8 +81,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsMasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsMasterSecretGenerator must be initialized");
         }
         SecretKey premasterKey = spec.getPremasterSecret();
         byte[] premaster = premasterKey.getEncoded();
@@ -103,7 +105,11 @@
 
             if (protocolVersion >= 0x0301) {
                 byte[] seed = concat(clientRandom, serverRandom);
-                master = doPRF(premaster, LABEL_MASTER_SECRET, seed, 48);
+                master = ((protocolVersion >= 0x0303) ?
+                    doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
+                        spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                        spec.getPRFBlockSize()) :
+                    doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
             } else {
                 master = new byte[48];
                 MessageDigest md5 = MessageDigest.getInstance("MD5");
@@ -124,7 +130,8 @@
 
             }
 
-            return new TlsMasterSecretKey(master, premasterMajor, premasterMinor);
+            return new TlsMasterSecretKey(master, premasterMajor,
+                premasterMinor);
         } catch (NoSuchAlgorithmException e) {
             throw new ProviderException(e);
         } catch (DigestException e) {
--- a/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,11 +37,15 @@
 
 /**
  * KeyGenerator implementation for the TLS PRF function.
+ * <p>
+ * This class duplicates the HMAC functionality (RFC 2104) with
+ * performance optimizations (e.g. XOR'ing keys with padding doesn't
+ * need to be redone for each HMAC operation).
  *
  * @author  Andreas Sterbenz
  * @since   1.6
  */
-public final class TlsPrfGenerator extends KeyGeneratorSpi {
+abstract class TlsPrfGenerator extends KeyGeneratorSpi {
 
     // magic constants and utility functions, also used by other files
     // in this package
@@ -69,8 +73,10 @@
      * TLS HMAC "inner" and "outer" padding.  This isn't a function
      * of the digest algorithm.
      */
-    private static final byte[] HMAC_ipad = genPad((byte)0x36, 64);
-    private static final byte[] HMAC_opad = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_ipad64  = genPad((byte)0x36, 64);
+    private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
+    private static final byte[] HMAC_opad64  = genPad((byte)0x5c, 64);
+    private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
 
     // SSL3 magic mix constants ("A", "BB", "CCC", ...)
     final static byte[][] SSL3_CONST = genConst();
@@ -123,8 +129,8 @@
         this.spec = (TlsPrfParameterSpec)params;
         SecretKey key = spec.getSecret();
         if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
-            throw new InvalidAlgorithmParameterException
-                ("Key encoding format must be RAW");
+            throw new InvalidAlgorithmParameterException(
+                "Key encoding format must be RAW");
         }
     }
 
@@ -132,17 +138,21 @@
         throw new InvalidParameterException(MSG);
     }
 
-    protected SecretKey engineGenerateKey() {
+    SecretKey engineGenerateKey0(boolean tls12) {
         if (spec == null) {
-            throw new IllegalStateException
-                ("TlsPrfGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsPrfGenerator must be initialized");
         }
         SecretKey key = spec.getSecret();
         byte[] secret = (key == null) ? null : key.getEncoded();
         try {
             byte[] labelBytes = spec.getLabel().getBytes("UTF8");
             int n = spec.getOutputLength();
-            byte[] prfBytes = doPRF(secret, labelBytes, spec.getSeed(), n);
+            byte[] prfBytes = (tls12 ?
+                doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
+                    spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                    spec.getPRFBlockSize()) :
+                doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
             return new SecretKeySpec(prfBytes, "TlsPrf");
         } catch (GeneralSecurityException e) {
             throw new ProviderException("Could not generate PRF", e);
@@ -151,16 +161,67 @@
         }
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength) throws NoSuchAlgorithmException, DigestException {
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            String prfHash, int prfHashLength, int prfBlockSize)
+            throws NoSuchAlgorithmException, DigestException {
+        if (prfHash == null) {
+            throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
+        }
+        MessageDigest prfMD = MessageDigest.getInstance(prfHash);
+        return doTLS12PRF(secret, labelBytes, seed, outputLength,
+            prfMD, prfHashLength, prfBlockSize);
+    }
+
+    static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength,
+            MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
+            throws DigestException {
+
+        if (secret == null) {
+            secret = B0;
+        }
+
+        // If we have a long secret, digest it first.
+        if (secret.length > mdPRFBlockSize) {
+            secret = mdPRF.digest(secret);
+        }
+
+        byte[] output = new byte[outputLength];
+        byte [] ipad;
+        byte [] opad;
+
+        switch (mdPRFBlockSize) {
+        case 64:
+            ipad = HMAC_ipad64.clone();
+            opad = HMAC_opad64.clone();
+            break;
+        case 128:
+            ipad = HMAC_ipad128.clone();
+            opad = HMAC_opad128.clone();
+            break;
+        default:
+            throw new DigestException("Unexpected block size.");
+        }
+
+        // P_HASH(Secret, label + seed)
+        expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
+            seed, output, ipad, opad);
+
+        return output;
+    }
+
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength) throws NoSuchAlgorithmException,
+            DigestException {
         MessageDigest md5 = MessageDigest.getInstance("MD5");
         MessageDigest sha = MessageDigest.getInstance("SHA1");
-        return doPRF(secret, labelBytes, seed, outputLength, md5, sha);
+        return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
     }
 
-    static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed,
-            int outputLength, MessageDigest md5, MessageDigest sha)
-            throws DigestException {
+    static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
+            byte[] seed, int outputLength, MessageDigest md5,
+            MessageDigest sha) throws DigestException {
         /*
          * Split the secret into two halves S1 and S2 of same length.
          * S1 is taken from the first half of the secret, S2 from the
@@ -183,10 +244,12 @@
         byte[] output = new byte[outputLength];
 
         // P_MD5(S1, label + seed)
-        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output);
+        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         // P_SHA-1(S2, label + seed)
-        expand(sha, 20, secret, off, seclen, labelBytes, seed, output);
+        expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
+            HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         return output;
     }
@@ -201,16 +264,13 @@
      * @param seed the seed
      * @param output the output array
      */
-    private static final void expand(MessageDigest digest, int hmacSize,
+    private static void expand(MessageDigest digest, int hmacSize,
             byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
-            byte[] output) throws DigestException {
+            byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
         /*
          * modify the padding used, by XORing the key into our copy of that
          * padding.  That's to avoid doing that for each HMAC computation.
          */
-        byte[] pad1 = HMAC_ipad.clone();
-        byte[] pad2 = HMAC_opad.clone();
-
         for (int i = 0; i < secLen; i++) {
             pad1[i] ^= secret[i + secOff];
             pad2[i] ^= secret[i + secOff];
@@ -275,7 +335,34 @@
             }
             remaining -= k;
         }
-
     }
 
+    /**
+     * A KeyGenerator implementation that supports TLS 1.2.
+     * <p>
+     * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
+     * calculations.  As of 2010, there is no PKCS11-level support for TLS
+     * 1.2 PRF calculations, and no known OS's have an internal variant
+     * we could use.  Therefore for TLS 1.2, we are updating JSSE to request
+     * a different provider algorithm:  "SunTls12Prf".  If we reused the
+     * name "SunTlsPrf", the PKCS11 provider would need be updated to
+     * fail correctly when presented with the wrong version number
+     * (via Provider.Service.supportsParameters()), and add the
+     * appropriate supportsParamters() checks into KeyGenerators (not
+     * currently there).
+     */
+    static public class V12 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(true);
+        }
+    }
+
+    /**
+     * A KeyGenerator implementation that supports TLS 1.0/1.1.
+     */
+    static public class V10 extends TlsPrfGenerator {
+        protected SecretKey engineGenerateKey() {
+            return engineGenerateKey0(false);
+        }
+    }
 }
--- a/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -69,8 +69,8 @@
 
     protected SecretKey engineGenerateKey() {
         if (spec == null) {
-            throw new IllegalStateException
-                    ("TlsRsaPremasterSecretGenerator must be initialized");
+            throw new IllegalStateException(
+                "TlsRsaPremasterSecretGenerator must be initialized");
         }
         if (random == null) {
             random = new SecureRandom();
--- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -45,7 +45,7 @@
     private boolean registered = false;
 
     public BMPImageReaderSpi() {
-        super("Sun Microsystems, Inc.",
+        super("Oracle Corporation",
               "1.0",
               formatNames,
               entensions,
--- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -50,7 +50,7 @@
     private boolean registered = false;
 
     public BMPImageWriterSpi() {
-        super("Sun Microsystems, Inc.",
+        super("Oracle Corporation",
               "1.0",
               formatNames,
               entensions,
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
 
 public class GIFImageReaderSpi extends ImageReaderSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
 
 public class GIFImageWriterSpi extends ImageWriterSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java	Thu Nov 18 10:35:46 2010 -0800
@@ -169,7 +169,7 @@
     public static final int ADOBE_YCCK = 2;
 
     // Spi initialization stuff
-    public static final String vendor = "Sun Microsystems, Inc.";
+    public static final String vendor = "Oracle Corporation";
     public static final String version = "0.5";
     // Names of the formats we can read or write
     public static final String [] names = {"JPEG", "jpeg", "JPG", "jpg"};
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
 
 public class PNGImageReaderSpi extends ImageReaderSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -38,7 +38,7 @@
 
 public class PNGImageWriterSpi extends ImageWriterSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -49,7 +49,7 @@
     private boolean registered = false;
 
     public WBMPImageReaderSpi() {
-        super("Sun Microsystems, Inc.",
+        super("Oracle Corporation",
               "1.0",
               formatNames,
               entensions,
--- a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -49,7 +49,7 @@
     private boolean registered = false;
 
     public WBMPImageWriterSpi() {
-        super("Sun Microsystems, Inc.",
+        super("Oracle Corporation",
               "1.0",
               formatNames,
               entensions,
--- a/src/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/FileImageInputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -33,7 +33,7 @@
 
 public class FileImageInputStreamSpi extends ImageInputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/FileImageOutputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -33,7 +33,7 @@
 
 public class FileImageOutputStreamSpi extends ImageOutputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/InputStreamImageInputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
 
 public class InputStreamImageInputStreamSpi extends ImageInputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/OutputStreamImageOutputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
 
 public class OutputStreamImageOutputStreamSpi extends ImageOutputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/RAFImageInputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -34,7 +34,7 @@
 
 public class RAFImageInputStreamSpi extends ImageInputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/imageio/spi/RAFImageOutputStreamSpi.java	Thu Nov 18 10:35:46 2010 -0800
@@ -34,7 +34,7 @@
 
 public class RAFImageOutputStreamSpi extends ImageOutputStreamSpi {
 
-    private static final String vendorName = "Sun Microsystems, Inc.";
+    private static final String vendorName = "Oracle Corporation";
 
     private static final String version = "1.0";
 
--- a/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Thu Nov 18 10:35:46 2010 -0800
@@ -654,8 +654,8 @@
         String layout;
         public FormatException(String message,
                                int ctype, String name, String layout) {
-            super(ATTR_CONTEXT_NAME[ctype]+"."+name
-                  +(message == null? "": (": "+message)));
+            super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" +
+                  (message == null? "" : (": " + message)));
             this.ctype = ctype;
             this.name = name;
             this.layout = layout;
--- a/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Thu Nov 18 10:35:46 2010 -0800
@@ -30,6 +30,7 @@
 import com.sun.java.util.jar.pack.Package.Class;
 import com.sun.java.util.jar.pack.Package.InnerClass;
 import com.sun.java.util.jar.pack.ConstantPool.*;
+import com.sun.tools.classfile.AttributeException;
 
 /**
  * Reader for a class file that is being incorporated into a package.
@@ -246,7 +247,9 @@
                     fixups[fptr++] = in.readUnsignedShort();
                     break;
                 default:
-                    throw new IOException("Bad constant pool tag "+tag);
+                    throw new ClassFormatException("Bad constant pool tag " +
+                            tag + " in File: " + cls.file.nameString +
+                            " at pos: " + inPos);
             }
         }
 
@@ -403,7 +406,7 @@
                     skip(length, "unknown "+name+" attribute in "+h);
                     continue;
                 } else {
-                    String message = "unknown in "+h;
+                    String message = " is unknown attribute in class " + h;
                     throw new Attribute.FormatException(message, ctype, name,
                                                         unknownAttrCommand);
                 }
@@ -415,7 +418,12 @@
                 if (a.name() == "Code") {
                     Class.Method m = (Class.Method) h;
                     m.code = new Code(m);
-                    readCode(m.code);
+                    try {
+                        readCode(m.code);
+                    } catch (Instruction.FormatException iie) {
+                        String message = iie.getMessage() + " in " + h;
+                        throw new ClassReader.ClassFormatException(message);
+                    }
                 } else {
                     assert(h == cls);
                     readInnerClasses(cls);
@@ -427,6 +435,10 @@
                 in.readFully(bytes);
                 a = a.addContent(bytes);
             }
+            if (a.size() == 0 && !a.layout().isEmpty()) {
+                throw new ClassFormatException(name +
+                        ": attribute length cannot be zero, in " + h);
+            }
             h.addAttribute(a);
             if (verbose > 2)
                 Utils.log.fine("read "+a);
@@ -438,6 +450,7 @@
         code.max_locals = readUnsignedShort();
         code.bytes = new byte[readInt()];
         in.readFully(code.bytes);
+        Instruction.opcodeChecker(code.bytes);
         int nh = readUnsignedShort();
         code.setHandlerCount(nh);
         for (int i = 0; i < nh; i++) {
@@ -463,4 +476,10 @@
         cls.innerClasses = ics;  // set directly; do not use setInnerClasses.
         // (Later, ics may be transferred to the pkg.)
     }
+
+    class ClassFormatException extends IOException {
+        public ClassFormatException(String message) {
+            super(message);
+        }
+    }
 }
--- a/src/share/classes/com/sun/java/util/jar/pack/Instruction.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/java/util/jar/pack/Instruction.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,6 +25,8 @@
 
 package com.sun.java.util.jar.pack;
 
+import java.io.IOException;
+
 /**
  * A parsed bytecode instruction.
  * Provides accessors to various relevant bits.
@@ -628,4 +630,21 @@
             }
         }
     }
+
+    public static void opcodeChecker(byte[] code) throws FormatException {
+        Instruction i = at(code, 0);
+        while (i != null) {
+            int opcode = i.getBC();
+            if (opcode == _xxxunusedxxx || opcode < _nop || opcode > _jsr_w) {
+                String message = "illegal opcode: " + opcode + " " + i;
+                throw new FormatException(message);
+            }
+            i = i.next();
+        }
+    }
+    static class FormatException extends IOException {
+        FormatException(String message) {
+            super(message);
+        }
+    }
 }
--- a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java	Thu Nov 18 10:35:46 2010 -0800
@@ -496,15 +496,29 @@
             reader.unknownAttrCommand = unknownAttrCommand;
             try {
                 reader.read();
-            } catch (Attribute.FormatException ee) {
-                // He passed up the category to us in layout.
-                if (ee.layout.equals(Pack200.Packer.PASS)) {
-                    Utils.log.warning("Passing class file uncompressed due to unrecognized attribute: "+fname);
-                    Utils.log.info(ee.toString());
-                    return null;
+            } catch (IOException ioe) {
+                String message = "Passing class file uncompressed due to";
+                if (ioe instanceof Attribute.FormatException) {
+                    Attribute.FormatException ee = (Attribute.FormatException) ioe;
+                    // He passed up the category to us in layout.
+                    if (ee.layout.equals(Pack200.Packer.PASS)) {
+                        Utils.log.info(ee.toString());
+                        Utils.log.warning(message + " unrecognized attribute: " +
+                                fname);
+                        return null;
+                    }
+                } else if (ioe instanceof ClassReader.ClassFormatException) {
+                    ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
+                    // %% TODO: Do we invent a new property for this or reuse %%
+                    if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
+                        Utils.log.info(ce.toString());
+                        Utils.log.warning(message + " unknown class format: " +
+                                fname);
+                        return null;
+                    }
                 }
                 // Otherwise, it must be an error.
-                throw ee;
+                throw ioe;
             }
             pkg.addClass(cls);
             return cls.file;
--- a/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/java/util/jar/pack/Utils.java	Thu Nov 18 10:35:46 2010 -0800
@@ -182,11 +182,8 @@
         }
 
         public void warning(String msg, Object param) {
-            int verbose = currentPropMap().getInteger(DEBUG_VERBOSE);
-            if (verbose > 0) {
                 getLogger().warning(msg, param);
             }
-        }
 
         public void warning(String msg) {
             warning(msg, null);
@@ -216,7 +213,9 @@
 
     // Returns the Max Version String of this implementation
     static String getVersionString() {
-        return "Pack200, Vendor: Sun Microsystems, Version: " +
+        return "Pack200, Vendor: " +
+            System.getProperty("java.vendor") +
+            ", Version: " +
             Constants.JAVA6_PACKAGE_MAJOR_VERSION + "." +
             Constants.JAVA6_PACKAGE_MINOR_VERSION;
     }
--- a/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/jmx/defaults/ServiceName.java	Thu Nov 18 10:35:46 2010 -0800
@@ -76,9 +76,9 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of this product implementing the  JMX specification.
@@ -91,7 +91,7 @@
      * The name of the vendor of this product implementing the
      * JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 }
--- a/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/jmx/snmp/ServiceName.java	Thu Nov 18 10:35:46 2010 -0800
@@ -27,7 +27,7 @@
 
 /**
  * Used for storing default values used by SNMP Runtime services.
- * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * <p><b>This API is an Oracle Corporation internal API  and is subject
  * to change without notice.</b></p>
  */
 public class ServiceName {
@@ -144,16 +144,16 @@
     /**
      * The vendor of the JMX specification implemented by this product.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_SPEC_VENDOR = "Sun Microsystems";
+    public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
 
     /**
      * The name of the vendor of this product implementing the  JMX specification.
      * <BR>
-     * The value is <CODE>Sun Microsystems</CODE>.
+     * The value is <CODE>Oracle Corporation</CODE>.
      */
-    public static final String JMX_IMPL_VENDOR = "Sun Microsystems";
+    public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
 
     /**
       * The build number of the current product version, of the form <CODE>rXX</CODE>.
--- a/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java	Thu Nov 18 10:35:46 2010 -0800
@@ -54,6 +54,7 @@
 public class DnsContextFactory implements InitialContextFactory {
 
     private static final String DEFAULT_URL = "dns:";
+    private static final int DEFAULT_PORT = 53;
 
 
     public Context getInitialContext(Hashtable<?,?> env) throws NamingException {
@@ -89,7 +90,9 @@
      * Public for use by product test suite.
      */
     public static boolean platformServersAvailable() {
-        return !ResolverConfiguration.open().nameservers().isEmpty();
+        return !filterNameServers(
+                    ResolverConfiguration.open().nameservers(), true
+                ).isEmpty();
     }
 
     private static Context urlToContext(String url, Hashtable env)
@@ -142,8 +145,8 @@
                 // No server or port given, so look to underlying platform.
                 // ResolverConfiguration does some limited caching, so the
                 // following is reasonably efficient even if called rapid-fire.
-                List<String> platformServers =
-                    ResolverConfiguration.open().nameservers();
+                List<String> platformServers = filterNameServers(
+                    ResolverConfiguration.open().nameservers(), false);
                 if (!platformServers.isEmpty()) {
                     servers.addAll(platformServers);
                     continue;  // on to next URL (if any, which is unlikely)
@@ -213,4 +216,44 @@
         String url = (String) env.get(Context.PROVIDER_URL);
         return ((url != null) ? url : DEFAULT_URL);
     }
+
+    /**
+     * Removes any DNS server that's not permitted to access
+     * @param input the input server[:port] list, must not be null
+     * @param oneIsEnough return output once there exists one ok
+     * @return the filtered list, all non-permitted input removed
+     */
+    private static List filterNameServers(List input, boolean oneIsEnough) {
+        SecurityManager security = System.getSecurityManager();
+        if (security == null || input == null || input.isEmpty()) {
+            return input;
+        } else {
+            List output = new ArrayList();
+            for (Object o: input) {
+                if (o instanceof String) {
+                    String platformServer = (String)o;
+                    int colon = platformServer.indexOf(':',
+                            platformServer.indexOf(']') + 1);
+
+                    int p = (colon < 0)
+                        ? DEFAULT_PORT
+                        : Integer.parseInt(
+                            platformServer.substring(colon + 1));
+                    String s = (colon < 0)
+                        ? platformServer
+                        : platformServer.substring(0, colon);
+                    try {
+                        security.checkConnect(s, p);
+                        output.add(platformServer);
+                        if (oneIsEnough) {
+                            return output;
+                        }
+                    } catch (SecurityException se) {
+                        continue;
+                    }
+                }
+            }
+            return output;
+        }
+    }
 }
--- a/src/share/classes/com/sun/management/package.html	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/management/package.html	Thu Nov 18 10:35:46 2010 -0800
@@ -30,7 +30,7 @@
 </head>
 <body bgcolor="white">
 
-This package contains Sun Microsystem's platform extension to
+This package contains Oracle Corporation's platform extension to
 the implementation of the
 <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html">
 java.lang.management</a> API and also defines the management
--- a/src/share/classes/com/sun/media/sound/RealTimeSequencer.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/media/sound/RealTimeSequencer.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1069,7 +1069,7 @@
     private static class RealTimeSequencerInfo extends MidiDevice.Info {
 
         private static final String name = "Real Time Sequencer";
-        private static final String vendor = "Sun Microsystems";
+        private static final String vendor = "Oracle Corporation";
         private static final String description = "Software sequencer";
         private static final String version = "Version 1.0";
 
--- a/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -24,9 +24,6 @@
  */
 
 package com.sun.net.httpserver;
-import java.net.*;
-import java.io.*;
-import java.util.*;
 
 /**
  * BasicAuthenticator provides an implementation of HTTP Basic
@@ -57,7 +54,6 @@
 
     public Result authenticate (HttpExchange t)
     {
-        HttpContext context = t.getHttpContext();
         Headers rmap = (Headers) t.getRequestHeaders();
         /*
          * look for auth token
--- a/src/share/classes/com/sun/net/httpserver/Filter.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/net/httpserver/Filter.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,11 +25,7 @@
 
 package com.sun.net.httpserver;
 
-import java.net.*;
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import sun.net.www.MessageHeader;
+import java.io.IOException;
 import java.util.*;
 
 /**
@@ -56,12 +52,10 @@
         /* the last element in the chain must invoke the users
          * handler
          */
-        private List<Filter> filters;
         private ListIterator<Filter> iter;
         private HttpHandler handler;
 
         public Chain (List<Filter> filters, HttpHandler handler) {
-            this.filters = filters;
             iter = filters.listIterator();
             this.handler = handler;
         }
--- a/src/share/classes/com/sun/net/httpserver/Headers.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/net/httpserver/Headers.java	Thu Nov 18 10:35:46 2010 -0800
@@ -26,7 +26,6 @@
 package com.sun.net.httpserver;
 
 import java.util.*;
-import java.io.*;
 
 /**
  * HTTP request and response headers are represented by this class which implements
@@ -77,19 +76,16 @@
             if (len == 0) {
                 return key;
             }
-            char[] b = new char [len];
-            String s = null;
-                b = key.toCharArray();
-                if (b[0] >= 'a' && b[0] <= 'z') {
-                    b[0] = (char)(b[0] - ('a' - 'A'));
+            char[] b = key.toCharArray();
+            if (b[0] >= 'a' && b[0] <= 'z') {
+                b[0] = (char)(b[0] - ('a' - 'A'));
+            }
+            for (int i=1; i<len; i++) {
+                if (b[i] >= 'A' && b[i] <= 'Z') {
+                    b[i] = (char) (b[i] + ('a' - 'A'));
                 }
-                for (int i=1; i<len; i++) {
-                    if (b[i] >= 'A' && b[i] <= 'Z') {
-                        b[i] = (char) (b[i] + ('a' - 'A'));
-                    }
-                }
-                s = new String (b);
-            return s;
+            }
+            return new String(b);
         }
 
         public int size() {return map.size();}
--- a/src/share/classes/com/sun/net/httpserver/HttpsParameters.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/net/httpserver/HttpsParameters.java	Thu Nov 18 10:35:46 2010 -0800
@@ -24,9 +24,7 @@
  */
 
 package com.sun.net.httpserver;
-import java.net.*;
-import java.io.*;
-import java.util.*;
+import java.net.InetSocketAddress;
 import javax.net.ssl.SSLParameters;
 
 /**
@@ -90,7 +88,7 @@
      * have been set.
      */
     public String[] getCipherSuites() {
-        return cipherSuites;
+        return cipherSuites != null ? cipherSuites.clone() : null;
     }
 
     /**
@@ -99,7 +97,7 @@
      * @param cipherSuites the array of ciphersuites (or null)
      */
     public void setCipherSuites(String[] cipherSuites) {
-        this.cipherSuites = cipherSuites;
+        this.cipherSuites = cipherSuites != null ? cipherSuites.clone() : null;
     }
 
     /**
@@ -110,7 +108,7 @@
      * have been set.
      */
     public String[] getProtocols() {
-        return protocols;
+        return protocols != null ? protocols.clone() : null;
     }
 
     /**
@@ -119,7 +117,7 @@
      * @param protocols the array of protocols (or null)
      */
     public void setProtocols(String[] protocols) {
-        this.protocols = protocols;
+        this.protocols = protocols != null ? protocols.clone() : null;
     }
 
     /**
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java	Thu Nov 18 10:35:46 2010 -0800
@@ -3,7 +3,7 @@
  * DO NOT REMOVE OR ALTER!
  */
 /*
- * Copyright  1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2010 The Apache Software Foundation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -23,66 +23,70 @@
 import java.io.OutputStream;
 
 /**
- * A simple Unsynced ByteArryOutputStream
+ * A simple Unsynced ByteArrayOutputStream
  * @author raul
  *
  */
 public class UnsyncByteArrayOutputStream extends OutputStream  {
-        private static ThreadLocal bufCahce = new ThreadLocal() {
+    private static final int INITIAL_SIZE = 8192;
+    private static ThreadLocal bufCache = new ThreadLocal() {
         protected synchronized Object initialValue() {
-            return new byte[8*1024];
+            return new byte[INITIAL_SIZE];
         }
     };
-    byte[] buf;
-        int size=8*1024;//buf.length;
-        int pos=0;
-        public UnsyncByteArrayOutputStream() {
-                buf=(byte[])bufCahce.get();
+
+    private byte[] buf;
+    private int size = INITIAL_SIZE;
+    private int pos = 0;
+
+    public UnsyncByteArrayOutputStream() {
+        buf = (byte[])bufCache.get();
+    }
+
+    public void write(byte[] arg0) {
+        int newPos = pos + arg0.length;
+        if (newPos > size) {
+            expandSize(newPos);
         }
-        /** @inheritDoc */
-        public void write(byte[] arg0) {
-                int newPos=pos+arg0.length;
-                if (newPos>size) {
-                        expandSize();
-                }
-                System.arraycopy(arg0,0,buf,pos,arg0.length);
-                pos=newPos;
+        System.arraycopy(arg0, 0, buf, pos, arg0.length);
+        pos = newPos;
+    }
+
+    public void write(byte[] arg0, int arg1, int arg2) {
+        int newPos = pos + arg2;
+        if (newPos > size) {
+            expandSize(newPos);
         }
-        /** @inheritDoc */
-        public void write(byte[] arg0, int arg1, int arg2) {
-                int newPos=pos+arg2;
-                if (newPos>size) {
-                        expandSize();
-                }
-                System.arraycopy(arg0,arg1,buf,pos,arg2);
-                pos=newPos;
+        System.arraycopy(arg0, arg1, buf, pos, arg2);
+        pos = newPos;
+    }
+
+    public void write(int arg0) {
+        int newPos = pos + 1;
+        if (newPos > size) {
+            expandSize(newPos);
         }
-        /** @inheritDoc */
-        public void write(int arg0) {
-                if (pos>=size) {
-                        expandSize();
-                }
-                buf[pos++]=(byte)arg0;
+        buf[pos++] = (byte)arg0;
+    }
+
+    public byte[] toByteArray() {
+        byte result[] = new byte[pos];
+        System.arraycopy(buf, 0, result, 0, pos);
+        return result;
+    }
+
+    public void reset() {
+        pos = 0;
+    }
+
+    private void expandSize(int newPos) {
+        int newSize = size;
+        while (newPos > newSize) {
+            newSize = newSize<<2;
         }
-        /** @inheritDoc */
-        public byte[] toByteArray() {
-                byte result[]=new byte[pos];
-                System.arraycopy(buf,0,result,0,pos);
-                return result;
-        }
-
-        /** @inheritDoc */
-        public void reset() {
-                pos=0;
-        }
-
-        /** @inheritDoc */
-        void expandSize() {
-                int newSize=size<<2;
-                byte newBuf[]=new byte[newSize];
-                System.arraycopy(buf,0,newBuf,0,pos);
-                buf=newBuf;
-                size=newSize;
-
-        }
+        byte newBuf[] = new byte[newSize];
+        System.arraycopy(buf, 0, newBuf, 0, pos);
+        buf = newBuf;
+        size = newSize;
+    }
 }
--- a/src/share/classes/java/awt/AWTEvent.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/AWTEvent.java	Thu Nov 18 10:35:46 2010 -0800
@@ -101,6 +101,12 @@
     transient boolean isPosted;
 
     /**
+     * Indicates whether this AWTEvent was generated by the system as
+     * opposed to by user code.
+     */
+    private transient boolean isSystemGenerated;
+
+    /**
      * The event mask for selecting component events.
      */
     public final static long COMPONENT_EVENT_MASK = 0x01;
@@ -235,6 +241,12 @@
                 public void setPosted(AWTEvent ev) {
                     ev.isPosted = true;
                 }
+                public void setSystemGenerated(AWTEvent ev) {
+                    ev.isSystemGenerated = true;
+                }
+                public boolean isSystemGenerated(AWTEvent ev) {
+                    return ev.isSystemGenerated;
+                }
             });
     }
 
@@ -554,6 +566,7 @@
                 }
             }
         }
+        that.isSystemGenerated = this.isSystemGenerated;
     }
 
     void dispatched() {
--- a/src/share/classes/java/awt/BasicStroke.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/BasicStroke.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package java.awt;
 
+import java.beans.ConstructorProperties;
+
 /**
  * The <code>BasicStroke</code> class defines a basic set of rendering
  * attributes for the outlines of graphics primitives, which are rendered
@@ -183,6 +185,7 @@
      *         <code>dash</code> is zero
      * @throws IllegalArgumentException if dash lengths are all zero.
      */
+    @ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" })
     public BasicStroke(float width, int cap, int join, float miterlimit,
                        float dash[], float dash_phase) {
         if (width < 0.0f) {
--- a/src/share/classes/java/awt/Canvas.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/Canvas.java	Thu Nov 18 10:35:46 2010 -0800
@@ -71,12 +71,13 @@
 
     @Override
     void setGraphicsConfiguration(GraphicsConfiguration gc) {
-        CanvasPeer peer = (CanvasPeer)getPeer();
-        if (peer != null) {
-            gc = peer.getAppropriateGraphicsConfiguration(gc);
+        synchronized(getTreeLock()) {
+            CanvasPeer peer = (CanvasPeer)getPeer();
+            if (peer != null) {
+                gc = peer.getAppropriateGraphicsConfiguration(gc);
+            }
+            super.setGraphicsConfiguration(gc);
         }
-
-        super.setGraphicsConfiguration(gc);
     }
 
     /**
--- a/src/share/classes/java/awt/Container.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/Container.java	Thu Nov 18 10:35:46 2010 -0800
@@ -4187,7 +4187,7 @@
             return true;
         }
 
-        for (Container cont = getContainer();
+        for (Container cont = this;
                 cont != null && cont.isLightweight();
                 cont = cont.getContainer())
         {
--- a/src/share/classes/java/awt/GradientPaint.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/GradientPaint.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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.awt.geom.Rectangle2D;
 import java.awt.geom.AffineTransform;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>GradientPaint</code> class provides a way to fill
@@ -166,6 +167,7 @@
      * @throws NullPointerException if either one of colors or points
      * is null
      */
+    @ConstructorProperties({ "point1", "color1", "point2", "color2", "cyclic" })
     public GradientPaint(Point2D pt1,
                          Color color1,
                          Point2D pt2,
--- a/src/share/classes/java/awt/GridBagConstraints.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/GridBagConstraints.java	Thu Nov 18 10:35:46 2010 -0800
@@ -126,7 +126,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the start of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTH for horizontal
+     * {@code ComponentOrientation}.  Equal to NORTH for horizontal
      * orientations.
      */
     public static final int PAGE_START = 19;
@@ -134,7 +134,7 @@
     /**
      * Place the component centered along the edge of its display area
      * associated with the end of a page for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTH for horizontal
+     * {@code ComponentOrientation}.  Equal to SOUTH for horizontal
      * orientations.
      */
     public static final int PAGE_END = 20;
@@ -142,7 +142,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to WEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to WEST for horizontal,
      * left-to-right orientations and EAST for horizontal, right-to-left
      * orientations.
      */
@@ -151,7 +151,7 @@
     /**
      * Place the component centered along the edge of its display area where
      * lines of text would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to EAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to EAST for horizontal,
      * left-to-right orientations and WEST for horizontal, right-to-left
      * orientations.
      */
@@ -160,7 +160,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally begin for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHWEST for horizontal,
      * left-to-right orientations and NORTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -169,7 +169,7 @@
     /**
      * Place the component in the corner of its display area where
      * the first line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to NORTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to NORTHEAST for horizontal,
      * left-to-right orientations and NORTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -178,7 +178,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally start for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHWEST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHWEST for horizontal,
      * left-to-right orientations and SOUTHEAST for horizontal, right-to-left
      * orientations.
      */
@@ -187,7 +187,7 @@
     /**
      * Place the component in the corner of its display area where
      * the last line of text on a page would normally end for the current
-     * <code>ComponentOrienation</code>.  Equal to SOUTHEAST for horizontal,
+     * {@code ComponentOrientation}.  Equal to SOUTHEAST for horizontal,
      * left-to-right orientations and SOUTHWEST for horizontal, right-to-left
      * orientations.
      */
@@ -437,7 +437,7 @@
      * <code>LINE_START</code>, <code>LINE_END</code>,
      * <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>,
      * <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>.  The
-     * baseline relvative values are:
+     * baseline relative values are:
      * <code>BASELINE</code>, <code>BASELINE_LEADING</code>,
      * <code>BASELINE_TRAILING</code>,
      * <code>ABOVE_BASELINE</code>, <code>ABOVE_BASELINE_LEADING</code>,
--- a/src/share/classes/java/awt/LinearGradientPaint.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/LinearGradientPaint.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,10 @@
 package java.awt;
 
 import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code LinearGradientPaint} class provides a way to fill
@@ -271,6 +271,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public LinearGradientPaint(Point2D start, Point2D end,
                                float[] fractions, Color[] colors,
                                CycleMethod cycleMethod,
--- a/src/share/classes/java/awt/RadialGradientPaint.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/RadialGradientPaint.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, 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.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
+import java.beans.ConstructorProperties;
 
 /**
  * The {@code RadialGradientPaint} class provides a way to fill a shape with
@@ -428,6 +429,7 @@
      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
      * or the {@code fractions} are not provided in strictly increasing order
      */
+    @ConstructorProperties({ "centerPoint", "radius", "focusPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
     public RadialGradientPaint(Point2D center,
                                float radius,
                                Point2D focus,
--- a/src/share/classes/java/awt/Scrollbar.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/Scrollbar.java	Thu Nov 18 10:35:46 2010 -0800
@@ -213,7 +213,8 @@
      * The size of the <code>Scrollbar</code>'s bubble.
      * When a scroll bar is used to select a range of values,
      * the visibleAmount represents the size of this range.
-     * This is visually indicated by the size of the bubble.
+     * Depending on platform, this may be visually indicated
+     * by the size of the bubble.
      *
      * @serial
      * @see #getVisibleAmount
@@ -637,6 +638,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
@@ -670,6 +673,8 @@
      * bubble (also called a thumb or scroll box), usually gives a
      * visual representation of the relationship of the visible
      * amount to the range of the scroll bar.
+     * Note that depending on platform, the value of the visible amount property
+     * may not be visually indicated by the size of the bubble.
      * <p>
      * The scroll bar's bubble may not be displayed when it is not
      * moveable (e.g. when it takes up the entire length of the
--- a/src/share/classes/java/awt/SequencedEvent.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/SequencedEvent.java	Thu Nov 18 10:35:46 2010 -0800
@@ -64,6 +64,9 @@
     public SequencedEvent(AWTEvent nested) {
         super(nested.getSource(), ID);
         this.nested = nested;
+        // All AWTEvents that are wrapped in SequencedEvents are (at
+        // least currently) implicitly generated by the system
+        SunToolkit.setSystemGenerated(nested);
         synchronized (SequencedEvent.class) {
             list.add(this);
         }
--- a/src/share/classes/java/awt/SplashScreen.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/SplashScreen.java	Thu Nov 18 10:35:46 2010 -0800
@@ -318,6 +318,12 @@
             checkVisible();
             _close(splashPtr);
             image = null;
+            SplashScreen.markClosed();
+        }
+    }
+
+    static void markClosed() {
+        synchronized (SplashScreen.class) {
             wasClosed = true;
             theInstance = null;
         }
--- a/src/share/classes/java/awt/Toolkit.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/Toolkit.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1831,7 +1831,11 @@
             desktopProperties.put(name, newValue);
         }
 
-        desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        // Don't fire change event if old and new values are null.
+        // It helps to avoid recursive resending of WM_THEMECHANGED
+        if (oldValue != null || newValue != null) {
+            desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+        }
     }
 
     /**
--- a/src/share/classes/java/awt/Window.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/Window.java	Thu Nov 18 10:35:46 2010 -0800
@@ -928,7 +928,10 @@
             return;
         }
         if (beforeFirstWindowShown.getAndSet(false)) {
+            // We don't use SplashScreen.getSplashScreen() to avoid instantiating
+            // the object if it hasn't been requested by user code explicitly
             SunToolkit.closeSplashScreen();
+            SplashScreen.markClosed();
         }
     }
 
--- a/src/share/classes/java/awt/event/InputEvent.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/event/InputEvent.java	Thu Nov 18 10:35:46 2010 -0800
@@ -29,8 +29,10 @@
 import java.awt.Component;
 import java.awt.GraphicsEnvironment;
 import java.awt.Toolkit;
+import java.util.Arrays;
+
+import sun.awt.AWTAccessor;
 import sun.util.logging.PlatformLogger;
-import java.util.Arrays;
 
 /**
  * The root event class for all component-level input events.
@@ -54,6 +56,7 @@
  * @since 1.1
  */
 public abstract class InputEvent extends ComponentEvent {
+
     private static final PlatformLogger logger = PlatformLogger.getLogger("java.awt.event.InputEvent");
 
     /**
@@ -288,6 +291,12 @@
         if (!GraphicsEnvironment.isHeadless()) {
             initIDs();
         }
+        AWTAccessor.setInputEventAccessor(
+            new AWTAccessor.InputEventAccessor() {
+                public int[] getButtonDownMasks() {
+                    return InputEvent.getButtonDownMasks();
+                }
+            });
     }
 
     /**
--- a/src/share/classes/java/awt/geom/AffineTransform.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/geom/AffineTransform.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package java.awt.geom;
 
 import java.awt.Shape;
+import java.beans.ConstructorProperties;
 
 /**
  * The <code>AffineTransform</code> class represents a 2D affine transform
@@ -508,6 +509,7 @@
      * @param m12 the Y coordinate translation element of the 3x3 matrix
      * @since 1.2
      */
+    @ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
     public AffineTransform(float m00, float m10,
                            float m01, float m11,
                            float m02, float m12) {
--- a/src/share/classes/java/awt/image/IndexColorModel.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/image/IndexColorModel.java	Thu Nov 18 10:35:46 2010 -0800
@@ -129,6 +129,8 @@
     private boolean allgrayopaque;
     private BigInteger validBits;
 
+    private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null;
+
     private static int[] opaqueBits = {8, 8, 8};
     private static int[] alphaBits = {8, 8, 8, 8};
 
@@ -1511,7 +1513,6 @@
      * longer referenced.
      */
     public void finalize() {
-        sun.awt.image.BufImgSurfaceData.freeNativeICMData(this);
     }
 
     /**
--- a/src/share/classes/java/awt/image/SampleModel.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/awt/image/SampleModel.java	Thu Nov 18 10:35:46 2010 -0800
@@ -358,6 +358,15 @@
         int cnt = 0;
         Object o = null;
 
+        int x1 = x + w;
+        int y1 = y + h;
+
+        if (x < 0 || x1 < x || x1 > width ||
+            y < 0 || y1 < y || y1 > height)
+        {
+            throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
+        }
+
         switch(type) {
 
         case DataBuffer.TYPE_BYTE:
@@ -370,8 +379,8 @@
             else
                 bdata = (byte[])obj;
 
-            for (int i=y; i<y+h; i++) {
-                for (int j=x; j<x+w; j++) {
+            for (int i=y; i<y1; i++) {
+                for (int j=x; j<x1; j++) {
                     o = getDataElements(j, i, o, data);
                     btemp = (byte[])o;
                     for (int k=0; k<numDataElems; k++) {
@@ -393,8 +402,8 @@
             else
                 sdata = (short[])obj;
 
-            for (int i=y; i<y+h; i++) {
-                for (int j=x; j<x+w; j++) {
+            for (int i=y; i<y1; i++) {
+                for (int j=x; j<x1; j++) {
                     o = getDataElements(j, i, o, data);
                     stemp = (short[])o;
                     for (int k=0; k<numDataElems; k++) {
@@ -416,8 +425,8 @@
             else
                 idata = (int[])obj;
 
-            for (int i=y; i<y+h; i++) {
-                for (int j=x; j<x+w; j++) {
+            for (int i=y; i<y1; i++) {
+                for (int j=x; j<x1; j++) {
                     o = getDataElements(j, i, o, data);
                     itemp = (int[])o;
                     for (int k=0; k<numDataElems; k++) {
@@ -439,8 +448,8 @@
             else
                 fdata = (float[])obj;
 
-            for (int i=y; i<y+h; i++) {
-                for (int j=x; j<x+w; j++) {
+            for (int i=y; i<y1; i++) {
+                for (int j=x; j<x1; j++) {
                     o = getDataElements(j, i, o, data);
                     ftemp = (float[])o;
                     for (int k=0; k<numDataElems; k++) {
@@ -462,8 +471,8 @@
             else
                 ddata = (double[])obj;
 
-            for (int i=y; i<y+h; i++) {
-                for (int j=x; j<x+w; j++) {
+            for (int i=y; i<y1; i++) {
+                for (int j=x; j<x1; j++) {
                     o = getDataElements(j, i, o, data);
                     dtemp = (double[])o;
                     for (int k=0; k<numDataElems; k++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/dyn/BootstrapMethod.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation on InvokeDynamic method calls which requests the JVM to use a specific
+ * <a href="package-summary.html#bsm">bootstrap method</a>
+ * to link the call.  This annotation is not retained as such in the class file,
+ * but is transformed into a constant-pool entry for the invokedynamic instruction which
+ * specifies the desired bootstrap method.
+ * <p>
+ * If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
+ * with a constructor which accepts a class, string, and method type.
+ * If the <code>value</code> and <code>name</code> are both given, there must be
+ * a static method in the given class of the given name which accepts a class, string,
+ * and method type, and returns a reference coercible to {@link CallSite}.
+ * <p>
+ * This annotation can be placed either on the return type of a single {@link InvokeDynamic}
+ * call (see examples) or else it can be placed on an enclosing class or method, where it
+ * determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
+ * specifically annotated with a bootstrap method.
+ * Every {@link InvokeDynamic} call must be given a bootstrap method.
+ * <p>
+ * Examples:
+<blockquote><pre>
+&#064;BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
+String x = (String) InvokeDynamic.greet();
+//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
+&#064;BootstrapMethod(MyCallSite.class)
+void example() throws Throwable {
+    InvokeDynamic.greet();
+    //BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
+}
+</pre></blockquote>
+ * <p>
+ */
+@Target({ElementType.TYPE_USE,
+            // For defaulting every indy site within a class or method; cf. @SuppressWarnings:
+            ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR
+            })
+@Retention(RetentionPolicy.SOURCE)
+public @interface BootstrapMethod {
+    /** The class containing the bootstrap method. */
+    Class<?> value();
+
+    /** The name of the bootstrap method.
+     *  If this is the empty string, an instance of the bootstrap class is created,
+     *  and a constructor is invoked.
+     *  Otherwise, there must be a static method of the required name.
+     */
+    String name() default "";  // empty string denotes a constructor with 'new'
+
+    /** The argument types of the bootstrap method, as passed out by the JVM.
+     *  There is usually no reason to override the default.
+     */
+    Class<?>[] arguments() default {Class.class, String.class, MethodType.class};
+}
--- a/src/share/classes/java/dyn/CallSite.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/CallSite.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,56 +25,26 @@
 
 package java.dyn;
 
-import sun.dyn.Access;
-import sun.dyn.MemberName;
-import sun.dyn.CallSiteImpl;
+import sun.dyn.*;
+import java.util.Collection;
 
 /**
- * A {@code CallSite} reifies an {@code invokedynamic} instruction from bytecode,
- * and controls its linkage.
- * Every linked {@code CallSite} object corresponds to a distinct instance
- * of the {@code invokedynamic} instruction, and vice versa.
+ * A {@code CallSite} is a holder for a variable {@link MethodHandle},
+ * which is called its {@code target}.
+ * Every call to a {@code CallSite} is delegated to the site's current target.
  * <p>
- * Every linked {@code CallSite} object has one state variable,
- * a {@link MethodHandle} reference called the {@code target}.
- * This reference is never null.  Though it can change its value
- * successive values must always have exactly the {@link MethodType method type}
- * called for by the bytecodes of the associated {@code invokedynamic} instruction
+ * A call site is initially created in an <em>unlinked</em> state,
+ * which is distinguished by a null target variable.
+ * Before the call site may be invoked (and before certain other
+ * operations are attempted), the call site must be linked to
+ * a non-null target.
  * <p>
- * It is the responsibility of each class's
- * {@link Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
- * to produce call sites which have been pre-linked to an initial target method.
- * The required {@link MethodType type} for the target method is a parameter
- * to each bootstrap method call.
- * <p>
- * The bootstrap method may elect to produce call sites of a
- * language-specific subclass of {@code CallSite}.  In such a case,
- * the subclass may claim responsibility for initializing its target to
- * a non-null value, by overriding {@link #initialTarget}.
- * <p>
- * An {@code invokedynamic} instruction which has not yet been executed
- * is said to be <em>unlinked</em>.  When an unlinked call site is executed,
- * the containing class's bootstrap method is called to manufacture a call site,
- * for the instruction.  If the bootstrap method does not assign a non-null
- * value to the new call site's target variable, the method {@link #initialTarget}
- * is called to produce the new call site's first target method.
- * <p>
- * A freshly-created {@code CallSite} object is not yet in a linked state.
- * An unlinked {@code CallSite} object reports null for its {@code callerClass}.
- * When the JVM receives a {@code CallSite} object from a bootstrap method,
- * it first ensures that its target is non-null and of the correct type.
- * The JVM then links the {@code CallSite} object to the call site instruction,
- * enabling the {@code callerClass} to return the class in which the instruction occurs.
- * <p>
- * Next, the JVM links the instruction to the {@code CallSite}, at which point
- * any further execution of the {@code invokedynamic} instruction implicitly
- * invokes the current target of the {@code CallSite} object.
- * After this two-way linkage, both the instruction and the {@code CallSite}
- * object are said to be linked.
- * <p>
- * This state of linkage continues until the method containing the
- * dynamic call site is garbage collected, or the dynamic call site
- * is invalidated by an explicit request.
+ * A call site may be <em>relinked</em> by changing its target.
+ * The new target must be non-null and must have the same
+ * {@linkplain MethodHandle#type() type}
+ * as the previous target.
+ * Thus, though a call site can be relinked to a series of
+ * successive targets, it cannot change its type.
  * <p>
  * Linkage happens once in the lifetime of any given {@code CallSite} object.
  * Because of call site invalidation, this linkage can be repeated for
@@ -87,6 +57,10 @@
  * Here is a sample use of call sites and bootstrap methods which links every
  * dynamic call site to print its arguments:
 <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
+&#064;BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
+static void test() throws Throwable {
+    InvokeDynamic.baz("baz arg", 2, 3.14);
+}
 private static void printArgs(Object... args) {
   System.out.println(java.util.Arrays.deepToString(args));
 }
@@ -96,17 +70,16 @@
   Class thisClass = lookup.lookupClass();  // (who am I?)
   printArgs = lookup.findStatic(thisClass,
       "printArgs", MethodType.methodType(void.class, Object[].class));
-  Linkage.registerBootstrapMethod("bootstrapDynamic");
 }
 private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
   // ignore caller and name, but match the type:
   return new CallSite(MethodHandles.collectArguments(printArgs, type));
 }
 </pre></blockquote>
- * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
  * @author John Rose, JSR 292 EG
  */
 public class CallSite
+    implements MethodHandleProvider
 {
     private static final Access IMPL_TOKEN = Access.getToken();
 
@@ -209,6 +182,7 @@
      * {@code InvokeDynamicBootstrapError}, which in turn causes the
      * linkage of the {@code invokedynamic} instruction to terminate
      * abnormally.
+     * @deprecated transitional form defined in EDR but removed in PFD
      */
     protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) {
         throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type);
@@ -278,16 +252,44 @@
      */
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder("CallSite#");
-        buf.append(hashCode());
-        if (!isLinked())
-            buf.append("[unlinked]");
-        else
-            buf.append("[")
-                .append("from ").append(vmmethod.getDeclaringClass().getName())
-                .append(" : ").append(getTarget().type())
-                .append(" => ").append(getTarget())
-                .append("]");
-        return buf.toString();
+        return "CallSite"+(target == null ? "" : target.type());
     }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle equivalent to an invokedynamic instruction
+     * which has been linked to this call site.
+     * <p>If this call site is a {@link ConstantCallSite}, this method
+     * simply returns the call site's target, since that will not change.
+     * <p>Otherwise, this method is equivalent to the following code:
+     * <p><blockquote><pre>
+     * MethodHandle getTarget, invoker, result;
+     * getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
+     * invoker = MethodHandles.exactInvoker(this.type());
+     * result = MethodHandles.foldArguments(invoker, getTarget)
+     * </pre></blockquote>
+     * @return a method handle which always invokes this call site's current target
+     */
+    public final MethodHandle dynamicInvoker() {
+        if (this instanceof ConstantCallSite)
+            return getTarget();  // will not change dynamically
+        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
+        MethodHandle invoker = MethodHandles.exactInvoker(this.type());
+        return MethodHandles.foldArguments(invoker, getTarget);
+    }
+    private static final MethodHandle GET_TARGET;
+    static {
+        try {
+            GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
+                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+        } catch (NoAccessException ignore) {
+            throw new InternalError();
+        }
+    }
+
+    /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
+    public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
+    public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/dyn/ClassValue.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Lazily associate a computed value with (potentially) every class.
+ * @author John Rose, JSR 292 EG
+ */
+public abstract class ClassValue<T> {
+    /**
+     * Compute the given class's derived value for this {@code ClassValue}.
+     * <p>
+     * This method will be invoked within the first thread that accesses
+     * the value with the {@link #get}.
+     * <p>
+     * Normally, this method is invoked at most once per class,
+     * but it may be invoked again in case of subsequent invocations
+     * of {@link #remove} followed by {@link #get}.
+     *
+     * @return the computed value for this thread-local
+     */
+    protected abstract T computeValue(Class<?> type);
+
+    /**
+     * Creates a new class value.
+     */
+    protected ClassValue() {
+    }
+
+    /**
+     * Returns the value for the given class.
+     * If no value has yet been computed, it is obtained by
+     * by an invocation of the {@link #computeValue} method.
+     * <p>
+     * The actual installation of the value on the class
+     * is performed while the class's synchronization lock
+     * is held.  At that point, if racing threads have
+     * computed values, one is chosen, and returned to
+     * all the racing threads.
+     *
+     * @return the current thread's value of this thread-local
+     */
+    public T get(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            Object x = map.get(this);
+            if (x != null) {
+                return (T) map.unmaskNull(x);
+            }
+        }
+        return setComputedValue(type);
+    }
+
+    /**
+     * Removes the associated value for the given class.
+     * If this value is subsequently {@linkplain #get read} for the same class,
+     * its value will be reinitialized by invoking its {@link #computeValue} method.
+     * This may result in an additional invocation of the
+     * {@code computeValue} method for the given class.
+     */
+    public void remove(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            synchronized (map) {
+                map.remove(this);
+            }
+        }
+    }
+
+    /// Implementation...
+
+    /** The hash code for this type is based on the identity of the object,
+     *  and is well-dispersed for power-of-two tables.
+     */
+    public final int hashCode() { return hashCode; }
+    private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
+    private static final AtomicInteger HASH_CODES = new AtomicInteger();
+
+    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+
+    /** Slow path for {@link #get}. */
+    private T setComputedValue(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map == null) {
+            map = initializeMap(type);
+        }
+        T value = computeValue(type);
+        STORE_BARRIER.lazySet(0);
+        // All stores pending from computeValue are completed.
+        synchronized (map) {
+            // Warm up the table with a null entry.
+            map.preInitializeEntry(this);
+        }
+        // All stores pending from table expansion are completed.
+        synchronized (map) {
+            value = (T) map.initializeEntry(this, value);
+            // One might fear a possible race condition here
+            // if the code for map.put has flushed the write
+            // to map.table[*] before the writes to the Map.Entry
+            // are done.  This is not possible, since we have
+            // warmed up the table with an empty entry.
+        }
+        return value;
+    }
+
+    // Replace this map by a per-class slot.
+    private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
+        = new WeakHashMap<Class<?>, ClassValueMap>();
+
+    private static ClassValueMap getMap(Class<?> type) {
+        return ROOT.get(type);
+    }
+
+    private static ClassValueMap initializeMap(Class<?> type) {
+        synchronized (ClassValue.class) {
+            ClassValueMap map = ROOT.get(type);
+            if (map == null)
+                ROOT.put(type, map = new ClassValueMap());
+            return map;
+        }
+    }
+
+    static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
+        /** Make sure this table contains an Entry for the given key, even if it is empty. */
+        void preInitializeEntry(ClassValue key) {
+            if (!this.containsKey(key))
+                this.put(key, null);
+        }
+        /** Make sure this table contains a non-empty Entry for the given key. */
+        Object initializeEntry(ClassValue key, Object value) {
+            Object prior = this.get(key);
+            if (prior != null) {
+                return unmaskNull(prior);
+            }
+            this.put(key, maskNull(value));
+            return value;
+        }
+
+        Object maskNull(Object x) {
+            return x == null ? this : x;
+        }
+        Object unmaskNull(Object x) {
+            return x == this ? null : x;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/dyn/ConstantCallSite.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+/**
+ * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
+ * The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
+ * to invalidate the instruction as a whole.
+ * @author John Rose, JSR 292 EG
+ */
+public class ConstantCallSite extends CallSite {
+    /** Create a call site with a permanent target. */
+    public ConstantCallSite(MethodHandle target) {
+        super(target);
+    }
+    /** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
+    @Override public final void setTarget(MethodHandle ignore) {
+        throw new IllegalArgumentException("ConstantCallSite");
+    }
+}
--- a/src/share/classes/java/dyn/InvokeDynamic.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/InvokeDynamic.java	Thu Nov 18 10:35:46 2010 -0800
@@ -35,7 +35,7 @@
  * The target method is a property of the reified {@linkplain CallSite call site object}
  * which is linked to each active {@code invokedynamic} instruction.
  * The call site object is initially produced by a
- * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
+ * {@linkplain BootstrapMethod bootstrap method}
  * associated with the class whose bytecodes include the dynamic call site.
  * <p>
  * The type {@code InvokeDynamic} has no particular meaning as a
@@ -45,22 +45,31 @@
  * It may be imported for ease of use.
  * <p>
  * Here are some examples:
- * <p><blockquote><pre>
- * Object x; String s; int i;
- * x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
- * s = InvokeDynamic.&lt;String&gt;hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
- * InvokeDynamic.&lt;void&gt;cogito(); // cogito()V
- * i = InvokeDynamic.&lt;int&gt;#"op:+"(2, 3); // "op:+"(II)I
- * </pre></blockquote>
+<blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
+&#064;BootstrapMethod(value=Here.class, name="bootstrapDynamic")
+static void example() throws Throwable {
+    Object x; String s; int i;
+    x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
+    s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
+    InvokeDynamic.cogito(); // cogito()V
+    i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
+}
+static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
+</pre></blockquote>
  * Each of the above calls generates a single invokedynamic instruction
  * with the name-and-type descriptors indicated in the comments.
+ * <p>
  * The argument types are taken directly from the actual arguments,
- * while the return type is taken from the type parameter.
- * (This type parameter may be a primtive, and it defaults to {@code Object}.)
+ * while the return type corresponds to the target of the assignment.
+ * (Currently, the return type must be given as a false type parameter.
+ * This type parameter is an irregular use of the generic type syntax,
+ * and is likely to change in favor of a convention based on target typing.)
+ * <p>
  * The final example uses a special syntax for uttering non-Java names.
  * Any name legal to the JVM may be given between the double quotes.
+ * <p>
  * None of these calls is complete without a bootstrap method,
- * which must be registered by the static initializer of the enclosing class.
+ * which must be declared for the enclosing class or method.
  * @author John Rose, JSR 292 EG
  */
 @MethodHandle.PolymorphicSignature
--- a/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Thu Nov 18 10:35:46 2010 -0800
@@ -28,19 +28,18 @@
 /**
  * Thrown to indicate that an {@code invokedynamic} instruction has
  * failed to find its
- * {@linkplain Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method},
+ * {@linkplain BootstrapMethod bootstrap method},
  * or the bootstrap method has
  * failed to provide a
  * {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target}
  * of the correct {@linkplain MethodType method type}.
- * <p>
- * The bootstrap method must have been declared during a class's initialization
- * by a call to one of the overloadings of
- * {@link Linkage#registerBootstrapMethod registerBootstrapMethod}.
  *
  * @author John Rose, JSR 292 EG
+ * @since 1.7
  */
 public class InvokeDynamicBootstrapError extends LinkageError {
+    private static final long serialVersionUID = 292L;
+
     /**
      * Constructs an {@code InvokeDynamicBootstrapError} with no detail message.
      */
@@ -63,10 +62,9 @@
      * detail message and cause.
      *
      * @param s the detail message.
-     * @param cause the cause.
+     * @param cause the cause, may be {@code null}.
      */
     public InvokeDynamicBootstrapError(String s, Throwable cause) {
-        super(s);
-        this.initCause(cause);
+        super(s, cause);
     }
 }
--- a/src/share/classes/java/dyn/JavaMethodHandle.java	Fri Oct 22 14:14:54 2010 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.Access;
-
-/**
- * A Java method handle is a deprecated proposal for extending
- * the basic method handle type with additional
- * programmer defined methods and fields.
- * Its behavior as a method handle is determined at instance creation time,
- * by providing the new instance with an "entry point" method handle
- * to handle calls.  This entry point must accept a leading argument
- * whose type is the Java method handle itself or a supertype, and the
- * entry point is always called with the Java method handle itself as
- * the first argument.  This is similar to ordinary virtual methods, which also
- * accept the receiver object {@code this} as an implicit leading argument.
- * The {@code MethodType} of the Java method handle is the same as that
- * of the entry point method handle, with the leading parameter type
- * omitted.
- * <p>
- * Here is an example of usage, creating a hybrid object/functional datum:
- * <p><blockquote><pre>
- * class Greeter extends JavaMethodHandle {
- *     private String greeting = "hello";
- *     public void setGreeting(String s) { greeting = s; }
- *     public void run() { System.out.println(greeting+", "+greetee); }
- *     private final String greetee;
- *     Greeter(String greetee) {
- *         super(RUN); // alternatively, super("run")
- *         this.greetee = greetee;
- *     }
- *     // the entry point function is computed once:
- *     private static final MethodHandle RUN
- *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
- *               MethodType.make(void.class));
- * }
- * // class Main { public static void main(String... av) { ...
- * Greeter greeter = new Greeter("world");
- * greeter.run();  // prints "hello, world"
- * // Statically typed method handle invocation (most direct):
- * MethodHandle mh = greeter;
- * mh.&lt;void&gt;invokeExact();  // also prints "hello, world"
- * // Dynamically typed method handle invocation:
- * MethodHandles.invokeExact(greeter);  // also prints "hello, world"
- * greeter.setGreeting("howdy");
- * mh.invokeExact();  // prints "howdy, world" (object-like mutable behavior)
- * </pre></blockquote>
- * <p>
- * In the example of {@code Greeter}, the method {@code run} provides the entry point.
- * The entry point need not be a constant value; it may be independently
- * computed in each call to the constructor.  The entry point does not
- * even need to be a method on the {@code Greeter} class, though
- * that is the typical case.
- * <p>
- * The entry point may also be provided symbolically, in which case the the
- * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
- * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
- * inner class:
- * <p><blockquote><pre>
- * // We can also do this with symbolic names and/or inner classes:
- * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
- *     void yow() { System.out.println("yow, world"); }
- * });
- * </pre></blockquote>
- * <p>
- * Here is similar lower-level code which works in terms of a bound method handle.
- * <p><blockquote><pre>
- *     class Greeter {
- *         public void run() { System.out.println("hello, "+greetee); }
- *         private final String greetee;
- *         Greeter(String greetee) { this.greetee = greetee; }
- *         // the entry point function is computed once:
- *         private static final MethodHandle RUN
- *             = MethodHandles.findVirtual(Greeter.class, "run",
- *                   MethodType.make(void.class));
- *     }
- *     // class Main { public static void main(String... av) { ...
- *     Greeter greeter = new Greeter("world");
- *     greeter.run();  // prints "hello, world"
- *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
- *     mh.invokeExact();  // also prints "hello, world"
- * </pre></blockquote>
- * Note that the method handle must be separately created as a view on the base object.
- * This increases footprint, complexity, and dynamic indirections.
- * <p>
- * Here is a pure functional value expressed most concisely as an anonymous inner class:
- * <p><blockquote><pre>
- *     // class Main { public static void main(String... av) { ...
- *     final String greetee = "world";
- *     MethodHandle greeter = new JavaMethodHandle("run") {
- *         private void run() { System.out.println("hello, "+greetee); }
- *     }
- *     greeter.invokeExact();  // prints "hello, world"
- * </pre></blockquote>
- * <p>
- * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
- * and instantiated as an anonymous class.  The data structure is a handle to 1-D array,
- * with a specialized index type (long).  It is created by inner class, and uses
- * signature-polymorphic APIs throughout.
- * <p><blockquote><pre>
- *     abstract class AssignableMethodHandle extends JavaMethodHandle {
- *       private final MethodHandle setter;
- *       public MethodHandle setter() { return setter; }
- *       public AssignableMethodHandle(String get, String set) {
- *         super(get);
- *         MethodType getType = this.type();
- *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
- *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
- *       }
- *     }
- *     // class Main { public static void main(String... av) { ...
- *     final Number[] stuff = { 123, 456 };
- *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
- *         public Number get(long i)           { return stuff[(int)i]; }
- *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
- *     }
- *     int x = (Integer) stuffPtr.&lt;Number&gt;invokeExact(1L);  // 456
- *     stuffPtr.setter().&lt;void&gt;invokeExact(0L, (Number) 789);  // replaces 123 with 789
- * </pre></blockquote>
- * @see MethodHandle
- * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
- * an interface-based API for mixing method handle behavior with other classes.
- * @author John Rose, JSR 292 EG
- */
-public abstract class JavaMethodHandle
-        // Note: This is an implementation inheritance hack, and will be removed
-        // with a JVM change which moves the required hidden behavior onto this class.
-        extends sun.dyn.BoundMethodHandle
-{
-    private static final Access IMPL_TOKEN = Access.getToken();
-
-    /**
-     * When creating a {@code JavaMethodHandle}, the actual method handle
-     * invocation behavior will be delegated to the specified {@code entryPoint}.
-     * This may be any method handle which can take the newly constructed object
-     * as a leading parameter.
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be {@code entryPoint}, minus the leading argument.
-     * The leading argument will be bound to {@code this} on every method
-     * handle invocation.
-     * @param entryPoint the method handle to handle calls
-     */
-    protected JavaMethodHandle(MethodHandle entryPoint) {
-        super(entryPoint);
-    }
-
-    /**
-     * Create a method handle whose entry point is a non-static method
-     * visible in the exact (most specific) class of
-     * the newly constructed object.
-     * <p>
-     * The method is specified by name and type, as if via this expression:
-     * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
-     * The class defining the method might be an anonymous inner class.
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be the given method handle type.
-     * A call to {@code this} will invoke the selected method.
-     * The receiver argument will be bound to {@code this} on every method
-     * handle invocation.
-     * <p>
-     * <i>Rationale:</i>
-     * Although this constructor may seem to be a mere luxury,
-     * it is not subsumed by the more general constructor which
-     * takes any {@code MethodHandle} as the entry point argument.
-     * In order to convert an entry point name to a method handle,
-     * the self-class of the object is required (in order to do
-     * the lookup).  The self-class, in turn, is generally not
-     * available at the time of the constructor invocation,
-     * due to the rules of Java and the JVM verifier.
-     * One cannot call {@code this.getClass()}, because
-     * the value of {@code this} is inaccessible at the point
-     * of the constructor call.  (Changing this would require
-     * change to the Java language, verifiers, and compilers.)
-     * In particular, this constructor allows {@code JavaMethodHandle}s
-     * to be created in combination with the anonymous inner class syntax.
-     * @param entryPointName the name of the entry point method
-     * @param type (optional) the desired type of the method handle
-     */
-    protected JavaMethodHandle(String entryPointName, MethodType type) {
-        super(entryPointName, type, true);
-
-    }
-
-    /**
-     * Create a method handle whose entry point is a non-static method
-     * visible in the exact (most specific) class of
-     * the newly constructed object.
-     * <p>
-     * The method is specified only by name.
-     * There must be exactly one method of that name visible in the object class,
-     * either inherited or locally declared.
-     * (That is, the method must not be overloaded.)
-     * <p>
-     * The method handle type of {@code this} (i.e, the fully constructed object)
-     * will be the same as the type of the selected non-static method.
-     * The receiver argument will be bound to {@code this} on every method
-     * handle invocation.
-     * <p>ISSUE: This signature wildcarding feature does not correspond to
-     * any MethodHandles.Lookup API element.  Can we eliminate it?
-     * Alternatively, it is useful for naming non-overloaded methods.
-     * Shall we make type arguments optional in the Lookup methods,
-     * throwing an error in cases of ambiguity?
-     * <p>
-     * For this method's rationale, see the documentation
-     * for {@link #JavaMethodHandle(String,MethodType)}.
-     * @param entryPointName the name of the entry point method
-     */
-    protected JavaMethodHandle(String entryPointName) {
-        super(entryPointName, (MethodType) null, false);
-    }
-}
--- a/src/share/classes/java/dyn/Linkage.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/Linkage.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,7 +25,6 @@
 
 package java.dyn;
 
-import java.lang.annotation.Annotation;
 import java.dyn.MethodHandles.Lookup;
 import java.util.WeakHashMap;
 import sun.dyn.Access;
@@ -56,11 +55,7 @@
      * <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
      * <li>the name of the method being invoked (a {@link String})
      * <li>the type of the method being invoked (a {@link MethodType})
-     * <li><em>TBD</em> optionally, an unordered array of {@link Annotation}s attached to the call site
-     *     <em>(Until this feature is implemented, this will always receive an empty array.)</em>
      * </ul>
-     * <em>(TBD: The final argument type may be missing from the method handle's type.
-     * Additional arguments may be added in the future.)</em>
      * The bootstrap method acts as a factory method which accepts the given arguments
      * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
      * <p>
@@ -86,6 +81,7 @@
      *            or is already running in another thread
      * @exception SecurityException if there is a security manager installed,
      *            and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
@@ -97,14 +93,9 @@
 
     static private void checkBSM(MethodHandle mh) {
         if (mh == null)  throw newIllegalArgumentException("null bootstrap method");
-        if (mh.type() == BOOTSTRAP_METHOD_TYPE_2)
-            // For now, always pass an empty array for the Annotations argument
-            mh = MethodHandles.insertArguments(mh, BOOTSTRAP_METHOD_TYPE_2.parameterCount()-1,
-                                               (Object)NO_ANNOTATIONS);
         if (mh.type() == BOOTSTRAP_METHOD_TYPE)  return;
         throw new WrongMethodTypeException(mh.toString());
     }
-    static private final Annotation[] NO_ANNOTATIONS = { };
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
@@ -115,6 +106,7 @@
      * @throws NoSuchMethodException if there is no such method
      * @throws IllegalStateException if the caller class's static initializer
      *         has already run, or is already running in another thread
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(Class<?> runtime, String name) {
@@ -131,6 +123,7 @@
      * @throws IllegalArgumentException if there is no such method
      * @throws IllegalStateException if the caller class's static initializer
      *         has already run, or is already running in another thread
+     * @deprecated Use @{@link BootstrapMethod} annotations instead
      */
     public static
     void registerBootstrapMethod(String name) {
@@ -142,18 +135,10 @@
     void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
         Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
         MethodHandle bootstrapMethod;
-        // Try both types.  TBD
         try {
-            bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE_2);
+            bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
         } catch (NoAccessException ex) {
-            bootstrapMethod = null;
-        }
-        if (bootstrapMethod == null) {
-            try {
-                bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
-            } catch (NoAccessException ex) {
-                throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
-            }
+            throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
         }
         checkBSM(bootstrapMethod);
         MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
@@ -172,6 +157,7 @@
      *            and the immediate caller of this method is not in the same
      *            package as the caller class
      *            and a {@link LinkagePermission} check fails for "getBootstrapMethod"
+     * @deprecated
      */
     public static
     MethodHandle getBootstrapMethod(Class callerClass) {
@@ -188,10 +174,6 @@
     public static final MethodType BOOTSTRAP_METHOD_TYPE
             = MethodType.methodType(CallSite.class,
                                     Class.class, String.class, MethodType.class);
-    static final MethodType BOOTSTRAP_METHOD_TYPE_2
-            = MethodType.methodType(CallSite.class,
-                                    Class.class, String.class, MethodType.class,
-                                    Annotation[].class);
 
     /**
      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
--- a/src/share/classes/java/dyn/LinkagePermission.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/LinkagePermission.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, 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
@@ -31,6 +31,7 @@
 import java.util.StringTokenizer;
 
 /**
+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  * This class is for managing runtime permission checking for
  * operations performed by methods in the {@link Linkage} class.
  * Like a {@link RuntimePermission}, on which it is modeled,
@@ -52,13 +53,6 @@
  * </tr>
  *
  * <tr>
- *   <td>registerBootstrapMethod.{class name}</td>
- *   <td>Specifying a bootstrap method for {@code invokedynamic} instructions within a class of the given name</td>
- *   <td>An attacker could attempt to attach a bootstrap method to a class which
- *       has just been loaded, thus gaining control of its {@code invokedynamic} calls.</td>
- * </tr>
- *
- * <tr>
  *   <td>invalidateAll</td>
  *   <td>Force the relinking of invokedynamic call sites everywhere.</td>
  *   <td>This could allow an attacker to slow down the system,
@@ -73,18 +67,21 @@
  *   <td>See {@code invalidateAll}.</td>
  * </tr>
  * </table>
+ * <p>ISSUE: Is this still needed?
  *
- * @see java.security.RuntimePermission
+ * @see java.lang.RuntimePermission
  * @see java.lang.SecurityManager
  *
  * @author John Rose, JSR 292 EG
  */
 
 public final class LinkagePermission extends BasicPermission {
+    private static final long serialVersionUID = 292L;
+
     /**
      * Create a new LinkagePermission with the given name.
      * The name is the symbolic name of the LinkagePermission, such as
-     * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk
+     * "invalidateCallerClass.*", etc. An asterisk
      * may appear at the end of the name, following a ".", or by itself, to
      * signify a wildcard match.
      *
--- a/src/share/classes/java/dyn/MethodHandle.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/MethodHandle.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,11 +36,13 @@
 /**
  * A method handle is a typed, directly executable reference to a method,
  * constructor, field, or similar low-level operation, with optional
- * conversion or substitution of arguments or return values.
+ * transformations of arguments or return values.
+ * (These transformations include conversion, insertion, deletion,
+ * substitution.  See the methods of this class and of {@link MethodHandles}.)
  * <p>
  * Method handles are strongly typed according to signature.
  * They are not distinguished by method name or enclosing class.
- * A method handle must be invoked under a signature which exactly matches
+ * A method handle must be invoked under a signature which matches
  * the method handle's own {@link MethodType method type}.
  * <p>
  * Every method handle confesses its type via the {@code type} accessor.
@@ -174,9 +176,10 @@
  * merely a documentation convention.  These type parameters do
  * not play a role in type-checking method handle invocations.
  * <p>
- * Note: Like classes and strings, method handles that correspond directly
- * to fields and methods can be represented directly as constants to be
- * loaded by {@code ldc} bytecodes.
+ * Like classes and strings, method handles that correspond to accessible
+ * fields, methods, and constructors can be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * Loading such a constant causes the component classes of its type to be loaded as necessary.
  *
  * @see MethodType
  * @see MethodHandles
@@ -186,6 +189,7 @@
         // Note: This is an implementation inheritance hack, and will be removed
         // with a JVM change which moves the required hidden state onto this class.
         extends MethodHandleImpl
+        implements MethodHandleProvider
 {
     private static Access IMPL_TOKEN = Access.getToken();
 
@@ -197,7 +201,7 @@
      * those methods which are signature polymorphic.
      */
     @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE})
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
     @interface PolymorphicSignature { }
 
     private MethodType type;
@@ -274,10 +278,14 @@
      * and performing simple conversions for arguments and return types.
      * The signature at the call site of {@code invokeGeneric} must
      * have the same arity as this method handle's {@code type}.
-     * The same conversions are allowed on arguments or return values as are supported by
-     * by {@link MethodHandles#convertArguments}.
+     * <p>
      * If the call site signature exactly matches this method handle's {@code type},
      * the call proceeds as if by {@link #invokeExact}.
+     * <p>
+     * Otherwise, the call proceeds as if this method handle were first
+     * adjusted by calling {@link #asType} to adjust this method handle
+     * to the required type, and then the call proceeds as if by
+     * {@link #invokeExact} on the adjusted method handle.
      */
     public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable;
 
@@ -538,4 +546,10 @@
     public final MethodHandle bindTo(Object x) {
         return MethodHandles.insertArguments(this, 0, x);
     }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */
+    public final MethodHandle asMethodHandle() { return this; }
+
+    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */
+    public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/dyn/MethodHandleProvider.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+/**
+ * An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
+ * There are many function-like objects in various Java APIs.
+ * This interface provides a standard way for such function-like objects to be bound
+ * to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
+ * <p>
+ * The type {@link MethodHandle} is a concrete class whose implementation
+ * hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
+ * It cannot also serve as a base type for user-defined functional APIs.
+ * For this reason, {@code MethodHandle} cannot be subclassed to add new
+ * behavior to method handles.  But this interface can be used to provide
+ * a link between a user-defined function and the {@code invokedynamic}
+ * instruction and the method handle API.
+ */
+public interface MethodHandleProvider {
+    /** Produce a method handle which will serve as a behavioral proxy for the current object.
+     *  The type and invocation behavior of the proxy method handle are user-defined,
+     *  and should have some relation to the intended meaning of the original object itself.
+     *  <p>
+     *  The current object may have a changeable behavior.
+     *  For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
+     *  In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
+     *  a method handle whose behavior may diverge from that of the current object.
+     *  Rather, the returned method handle must stably and permanently access
+     *  the behavior of the current object, even if that behavior is changeable.
+     *  <p>
+     *  The reference identity of the proxy method handle is not guaranteed to
+     *  have any particular relation to the reference identity of the object.
+     *  In particular, several objects with the same intended meaning could
+     *  share a common method handle, or the same object could return different
+     *  method handles at different times.  In the latter case, the different
+     *  method handles should have the same type and invocation behavior,
+     *  and be usable from any thread at any time.
+     *  In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
+     *  call site, the proxy method handle extracted at the time of binding
+     *  will be used for an unlimited time, until the call site is rebound.
+     *  <p>
+     *  The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
+     *  for this method simply returns {@code this}.
+     */
+    public MethodHandle asMethodHandle();
+
+    /** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
+     *  As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
+     *  proxy method handle is user-defined.  But the type must be the given type,
+     *  or else a {@link WrongMethodTypeException} must be thrown.
+     *  <p>
+     *  If the current object somehow represents a variadic or overloaded behavior,
+     *  the method handle returned for a given type might represent only a subset of
+     *  the current object's repertoire of behaviors, which correspond to that type.
+     */
+    public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException;
+}
--- a/src/share/classes/java/dyn/MethodHandles.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/MethodHandles.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,15 +25,12 @@
 
 package java.dyn;
 
-import java.lang.reflect.Constructor;
+import java.lang.reflect.*;
 import sun.dyn.Access;
 import sun.dyn.MemberName;
 import sun.dyn.MethodHandleImpl;
 import sun.dyn.util.VerifyAccess;
 import sun.dyn.util.Wrapper;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -81,6 +78,14 @@
      * Return a {@link Lookup lookup object} which is trusted minimally.
      * It can only be used to create method handles to
      * publicly accessible fields and methods.
+     * <p>
+     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
+     * of this lookup object will be {@link java.lang.Object}.
+     * <p>
+     * The lookup class can be changed to any other class {@code C} using an expression of the form
+     * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
+     * Since all classes have equal access to public names,
+     * such a change would confer no new access rights.
      */
     public static Lookup publicLookup() {
         return Lookup.PUBLIC_LOOKUP;
@@ -90,9 +95,10 @@
      * A <em>lookup object</em> is a factory for creating method handles,
      * when the creation requires access checking.
      * Method handles do not perform
-     * access checks when they are called; this is a major difference
+     * access checks when they are called, but rather when they are created.
+     * (This is a major difference
      * from reflective {@link Method}, which performs access checking
-     * against every caller, on every call.
+     * against every caller, on every call.)
      * Therefore, method handle access
      * restrictions must be enforced when a method handle is created.
      * The caller class against which those restrictions are enforced
@@ -107,7 +113,7 @@
      * It may then use this factory to create method handles on
      * all of its methods, including private ones.
      * It may also delegate the lookup (e.g., to a metaobject protocol)
-     * by passing the {@code Lookup} object to other code.
+     * by passing the lookup object to other code.
      * If this other code creates method handles, they will be access
      * checked against the original lookup class, and not with any higher
      * privileges.
@@ -125,23 +131,28 @@
      * It can also fail if a security manager is installed and refuses
      * access.  In any of these cases, an exception will be
      * thrown from the attempted lookup.
+     * <p>
      * In general, the conditions under which a method handle may be
      * created for a method {@code M} are exactly as restrictive as the conditions
      * under which the lookup class could have compiled a call to {@code M}.
-     * At least some of these error conditions are likely to be
-     * represented by checked exceptions in the final version of this API.
+     * This rule is applied even if the Java compiler might have created
+     * an wrapper method to access a private method of another class
+     * in the same top-level declaration.
+     * For example, a lookup object created for a nested class {@code C.D}
+     * can access private members within other related classes such as
+     * {@code C}, {@code C.D.E}, or {@code C.B}.
      */
     public static final
     class Lookup {
         /** The class on behalf of whom the lookup is being performed. */
         private final Class<?> lookupClass;
 
-        /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
+        /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */
         private final int allowedModes;
 
         private static final int
             PUBLIC    = Modifier.PUBLIC,
-            PACKAGE   = Modifier.STRICT,
+            PACKAGE   = Modifier.STATIC,
             PROTECTED = Modifier.PROTECTED,
             PRIVATE   = Modifier.PRIVATE,
             ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
@@ -155,8 +166,10 @@
         /** Which class is performing the lookup?  It is this class against
          *  which checks are performed for visibility and access permissions.
          *  <p>
-         *  This value is null if and only if this lookup was produced
-         *  by {@link MethodHandles#publicLookup}.
+         *  The class implies a maximum level of access permission,
+         *  but the permissions may be additionally limited by the bitmask
+         *  {@link #lookupModes}, which controls whether non-public members
+         *  can be accessed.
          */
         public Class<?> lookupClass() {
             return lookupClass;
@@ -168,10 +181,15 @@
         }
 
         /** Which types of members can this lookup object produce?
-         *  The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
-         *  The modifier bit STRICT stands in for the (non-existent) package protection mode.
+         *  The result is a bit-mask of the {@link Modifier} bits
+         *  {@linkplain Modifier#PUBLIC PUBLIC (0x01)},
+         *  {@linkplain Modifier#PROTECTED PROTECTED (0x02)},
+         *  {@linkplain Modifier#PRIVATE PRIVATE (0x04)},
+         *  and {@linkplain Modifier#STATIC STATIC (0x08)}.
+         *  The modifier bit {@code STATIC} stands in for the package protection mode,
+         *  which does not have an explicit modifier bit.
          */
-        int lookupModes() {
+        public int lookupModes() {
             return allowedModes & ALL_MODES;
         }
 
@@ -621,32 +639,32 @@
 
         /// Helper methods, all package-private.
 
-        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
+        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
         }
 
-        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
+        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
         }
 
         MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
-                                 boolean searchSupers, Class<?> specialCaller) {
+                                 boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
             checkSymbolicClass(refc);  // do this before attempting to resolve
             int mods = (isStatic ? Modifier.STATIC : 0);
             return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
         }
 
-        void checkSymbolicClass(Class<?> refc) {
+        void checkSymbolicClass(Class<?> refc) throws NoAccessException {
             Class<?> caller = lookupClassOrNull();
             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
                 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
         }
 
-        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
+        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
             String message;
             if (m.isConstructor())
                 message = "expected a method, not a constructor";
@@ -659,7 +677,7 @@
             throw newNoAccessException(message, m, lookupClass());
         }
 
-        void checkAccess(Class<?> refc, MemberName m) {
+        void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
             int allowedModes = this.allowedModes;
             if (allowedModes == TRUSTED)  return;
             int mods = m.getModifiers();
@@ -695,14 +713,14 @@
             return "member is private to package";
         }
 
-        void checkSpecialCaller(Class<?> specialCaller) {
+        void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
             if (allowedModes == TRUSTED)  return;
             if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
                 throw newNoAccessException("no private access for invokespecial",
                                            new MemberName(specialCaller), lookupClass());
         }
 
-        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
+        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
             // The accessing class only has the right to use a protected member
             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
             if (!method.isProtected() || method.isStatic()
@@ -712,7 +730,7 @@
             else
                 return restrictReceiver(method, mh, lookupClass());
         }
-        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
+        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
             assert(!method.isStatic());
             Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
             if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
@@ -898,11 +916,16 @@
      * @return a method handle which always invokes the call site's target
      */
     public static
-    MethodHandle dynamicInvoker(CallSite site) {
+    MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
         MethodHandle getCSTarget = GET_TARGET;
-        if (getCSTarget == null)
-            GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
-                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+        if (getCSTarget == null) {
+            try {
+                GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
+                    findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+            } catch (NoAccessException ex) {
+                throw new InternalError();
+            }
+        }
         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
         MethodHandle invoker = exactInvoker(site.type());
         return foldArguments(invoker, getTarget);
@@ -1260,17 +1283,20 @@
      * <p>
      * <b>Example:</b>
      * <p><blockquote><pre>
-     *   MethodHandle cat = MethodHandles.lookup().
-     *     findVirtual(String.class, "concat", String.class, String.class);
-     *   System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy
+     *   import static java.dyn.MethodHandles.*;
+     *   import static java.dyn.MethodType.*;
+     *   ...
+     *   MethodHandle cat = lookup().findVirtual(String.class,
+     *     "concat", methodType(String.class, String.class));
+     *   System.out.println((String) cat.invokeExact("x", "y")); // xy
      *   MethodHandle d0 = dropArguments(cat, 0, String.class);
-     *   System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy
+     *   System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
      *   MethodHandle d1 = dropArguments(cat, 1, String.class);
-     *   System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz
+     *   System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
      *   MethodHandle d2 = dropArguments(cat, 2, String.class);
-     *   System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz
-     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
-     *   System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz
+     *   System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
+     *   MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+     *   System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
      * </pre></blockquote>
      * @param target the method handle to invoke after the argument is dropped
      * @param valueTypes the type(s) of the argument to drop
@@ -1562,4 +1588,107 @@
     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
         return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
     }
+
+    /**
+     * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
+     * A SAM type is a type which declares a single abstract method.
+     * Additionally, it must have either no constructor (as an interface)
+     * or have a public or protected constructor of zero arguments (as a class).
+     * <p>
+     * The resulting instance of the required SAM type will respond to
+     * invocation of the SAM type's single abstract method by calling
+     * the given {@code target} on the incoming arguments,
+     * and returning or throwing whatever the {@code target}
+     * returns or throws.  The invocation will be as if by
+     * {@code target.invokeExact}.
+     * <p>
+     * The method handle may throw an <em>undeclared exception</em>,
+     * which means any checked exception (or other checked throwable)
+     * not declared by the SAM type's single abstract method.
+     * If this happens, the throwable will be wrapped in an instance
+     * of {@link UndeclaredThrowableException} and thrown in that
+     * wrapped form.
+     * <p>
+     * The wrapper instance is guaranteed to be of a non-public
+     * implementation class C in a package containing no classes
+     * or methods except system-defined classes and methods.
+     * The implementation class C will have no public supertypes
+     * or public methods beyond the following:
+     * <ul>
+     * <li>the SAM type itself and any methods in the SAM type
+     * <li>the supertypes of the SAM type (if any) and their methods
+     * <li>{@link Object} and its methods
+     * <li>{@link MethodHandleProvider} and its methods
+     * </ul>
+     * <p>
+     * No stable mapping is promised between the SAM type and
+     * the implementation class C.  Over time, several implementation
+     * classes might be used for the same SAM type.
+     * <p>
+     * This method is not guaranteed to return a distinct
+     * wrapper object for each separate call.  If the JVM is able
+     * to prove that a wrapper has already been created for a given
+     * method handle, or for another method handle with the
+     * same behavior, the JVM may return that wrapper in place of
+     * a new wrapper.
+     * @param target the method handle to invoke from the wrapper
+     * @param samType the desired type of the wrapper, a SAM type
+     * @return a correctly-typed wrapper for the given {@code target}
+     * @throws IllegalArgumentException if the {@code target} throws
+     *         an undeclared exception
+     */
+    // ISSUE: Should we delegate equals/hashCode to the targets?
+    // Not useful unless there is a stable equals/hashCode behavior
+    // for MethodHandle, and for MethodHandleProvider.asMethodHandle.
+    public static
+    <T> T asInstance(MethodHandle target, Class<T> samType) {
+        // POC implementation only; violates the above contract several ways
+        final Method sam = getSamMethod(samType);
+        if (sam == null)
+            throw new IllegalArgumentException("not a SAM type: "+samType.getName());
+        MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
+        if (!samMT.equals(target.type()))
+            throw new IllegalArgumentException("wrong method type");
+        final MethodHandle mh = target;
+        return samType.cast(Proxy.newProxyInstance(
+                samType.getClassLoader(),
+                new Class[]{ samType, MethodHandleProvider.class },
+                new InvocationHandler() {
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        if (method.getDeclaringClass() == MethodHandleProvider.class) {
+                            return method.invoke(mh, args);
+                        }
+                        assert method.equals(sam) : method;
+                        return mh.invokeVarargs(args);
+                    }
+                }));
+    }
+
+    private static
+    Method getSamMethod(Class<?> samType) {
+        Method sam = null;
+        for (Method m : samType.getMethods()) {
+            int mod = m.getModifiers();
+            if (Modifier.isAbstract(mod)) {
+                if (sam != null)
+                    return null;  // too many abstract methods
+                sam = m;
+            }
+        }
+        if (!samType.isInterface() && getSamConstructor(samType) == null)
+            return null;  // wrong kind of constructor
+        return sam;
+    }
+
+    private static
+    Constructor getSamConstructor(Class<?> samType) {
+        for (Constructor c : samType.getDeclaredConstructors()) {
+            if (c.getParameterTypes().length == 0) {
+                int mod = c.getModifiers();
+                if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
+                    return c;
+            }
+        }
+        return null;
+    }
 }
--- a/src/share/classes/java/dyn/MethodType.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/MethodType.java	Thu Nov 18 10:35:46 2010 -0800
@@ -40,24 +40,37 @@
  * returned by a method handle, or the arguments and return type passed
  * and expected  by a method handle caller.  Method types must be properly
  * matched between a method handle and all its callers,
- * and the JVM's operations enforce this matching at all times.
+ * and the JVM's operations enforce this matching at, specifically
+ * during calls to {@link MethodHandle#invokeExact}
+ * and {@link MethodHandle#invokeGeneric}, and during execution
+ * of {@code invokedynamic} instructions.
  * <p>
  * The structure is a return type accompanied by any number of parameter types.
- * The types (primitive, void, and reference) are represented by Class objects.
+ * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
+ * (For ease of exposition, we treat {@code void} as if it were a type.
+ * In fact, it denotes the absence of a return type.)
  * <p>
- * All instances of <code>MethodType</code> are immutable.
+ * All instances of {@code MethodType} are immutable.
  * Two instances are completely interchangeable if they compare equal.
  * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
  * <p>
  * This type can be created only by factory methods.
  * All factory methods may cache values, though caching is not guaranteed.
  * <p>
- * Note: Like classes and strings, method types can be represented directly
- * as constants to be loaded by {@code ldc} bytecodes.
+ * {@code MethodType} objects are sometimes derived from bytecode instructions
+ * such as {@code invokedynamic}, specifically from the type descriptor strings associated
+ * with the instructions in a class file's constant pool.
+ * When this occurs, any classes named in the descriptor strings must be loaded.
+ * (But they need not be initialized.)
+ * This loading may occur at any time before the {@code MethodType} object is first derived.
+ * <p>
+ * Like classes and strings, method types can be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * Loading such a constant causes its component classes to be loaded as necessary.
  * @author John Rose, JSR 292 EG
  */
 public final
-class MethodType {
+class MethodType implements java.lang.reflect.Type {
     private final Class<?>   rtype;
     private final Class<?>[] ptypes;
     private MethodTypeForm form; // erased form, plus cached data about primitives
@@ -636,11 +649,11 @@
 
     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
      * Find or create an instance of the given method type.
-     * Any class or interface name embedded in the signature string
+     * Any class or interface name embedded in the descriptor string
      * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
      * on the given loader (or if it is null, on the system class loader).
      * <p>
-     * Note that it is possible to build method types which cannot be
+     * Note that it is possible to encounter method types which cannot be
      * constructed by this method, because their component types are
      * not all reachable from a common class loader.
      * <p>
@@ -662,8 +675,11 @@
     }
 
     /**
-     * Create a bytecode signature representation of the type.
-     * Note that this is not a strict inverse of
+     * Create a bytecode descriptor representation of the method type.
+     * <p>
+     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString}.
+     * Two distinct classes which share a common name but have different class loaders
+     * will appear identical when viewed within descriptor strings.
      * <p>
      * This method is included for the benfit of applications that must
      * generate bytecodes that process method handles and invokedynamic.
--- a/src/share/classes/java/dyn/NoAccessException.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/NoAccessException.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,11 @@
  * on behalf of the method handle creator,
  * at the time of creation.
  * @author John Rose, JSR 292 EG
+ * @since 1.7
  */
-public class NoAccessException extends RuntimeException {
+public class NoAccessException extends ReflectiveOperationException {
+    private static final long serialVersionUID = 292L;
+
     /**
      * Constructs a {@code NoAccessException} with no detail message.
      */
--- a/src/share/classes/java/dyn/WrongMethodTypeException.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/WrongMethodTypeException.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,11 @@
  * instead of when the mismatched method handle is called.
  *
  * @author John Rose, JSR 292 EG
+ * @since 1.7
  */
 public class WrongMethodTypeException extends RuntimeException {
+    private static final long serialVersionUID = 292L;
+
     /**
      * Constructs a {@code WrongMethodTypeException} with no detail message.
      */
--- a/src/share/classes/java/dyn/package-info.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/dyn/package-info.java	Thu Nov 18 10:35:46 2010 -0800
@@ -40,20 +40,18 @@
  * The JVM links any such call (regardless of signature) to a dynamically
  * typed method handle invocation.  In the case of {@code invokeGeneric},
  * argument and return value conversions are applied.
+ * </li>
  *
- * <li>In source code, the class {@link java.dyn.InvokeDynamic} appears to accept
+ * <li>In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
  * any static method invocation, of any name and any signature.
  * But instead of emitting
  * an {@code invokestatic} instruction for such a call, the Java compiler emits
  * an {@code invokedynamic} instruction with the given name and signature.
- *
- * <li>When the JVM links an {@code invokedynamic} instruction, it calls the
- * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
- * of the containing class to obtain a {@linkplain java.dyn.CallSite call site} object through which
- * the call site will link its target {@linkplain java.dyn.MethodHandle method handle}.
+ * </li>
  *
  * <li>The JVM bytecode format supports immediate constants of
- * the classes {@link java.dyn.MethodHandle} and {@link java.dyn.MethodType}.
+ * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
+ * </li>
  * </ul>
  *
  * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
@@ -65,18 +63,50 @@
  * The first byte is the opcode 186 (hexadecimal {@code BA}).
  * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
  * The final two bytes are reserved for future use and required to be zero.
- * The constant pool reference is to a entry with tag {@code CONSTANT_NameAndType}
- * (decimal 12).  It is thus not a method reference of any sort, but merely
- * the method name, argument types, and return type of the dynamic call site.
- * <em>(TBD: The EG is discussing the possibility of a special constant pool entry type,
- * so that other information may be added, such as a per-instruction bootstrap
- * method and/or annotations.)</em>
+ * The constant pool reference of an {@code invokedynamic} instruction is to a entry
+ * with tag {@code CONSTANT_InvokeDynamic} (decimal 17).  See below for its format.
+ * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
+ * the dynamic invocation name, and the argument types and return type of the call.
+ * <p>
+ * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
+ * Multiple instances of an {@code invokedynamic} instruction can share a single
+ * {@code CONSTANT_InvokeDynamic} entry.
+ * In any case, distinct call sites always have distinct linkage state.
+ * <p>
+ * Moreover, for the purpose of distinguishing dynamic call sites,
+ * the JVM is allowed (but not required) to make internal copies
+ * of {@code invokedynamic} instructions, each one
+ * constituting a separate dynamic call site with its own linkage state.
+ * Such copying, if it occurs, cannot be observed except indirectly via
+ * execution of bootstrap methods and target methods.
+ * <p>
+ * A dynamic call site is originally in an unlinked state.  In this state, there is
+ * no target method for the call site to invoke.
+ * A dynamic call site is linked by means of a bootstrap method,
+ * as <a href="#bsm">described below</a>.
+ * <p>
+ * <em>(Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
+ * instead of a {@code CONSTANT_InvokeDynamic}.  In earlier, obsolete versions of this API, the
+ * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)</em>
+ *
+ * <h3>constant pool entries for {@code invokedynamic} instructions</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
+ * it must contain exactly four more bytes.
+ * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
+ * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
+ * The first index specifies a bootstrap method used by the associated dynamic call sites.
+ * The second index specifies the method name, argument types, and return type of the dynamic call site.
+ * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
+ * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
+ * is replaced by a bootstrap method reference.
  *
  * <h3>constant pool entries for {@code MethodType}s</h3>
  * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
- * it must contain exactly two more bytes, which are an index to a {@code CONSTANT_Utf8}
- * entry which represents a method type signature.  The JVM will ensure that on first
- * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType}
+ * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
+ * entry which represents a method type signature.
+ * <p>
+ * The JVM will ensure that on first
+ * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
  * will be created which represents the signature.
  * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
  * but not initialized.
@@ -86,12 +116,15 @@
  * <h3>constant pool entries for {@code MethodHandle}s</h3>
  * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
  * it must contain exactly three more bytes.  The first byte after the tag is a subtag
- * value in the range 1 through 9, and the last two are an index to a
+ * value which must be in the range 1 through 9, and the last two must be an index to a
  * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
  * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
  * for which a method handle is to be created.
+ * Furthermore, the subtag value and the type of the constant index value
+ * must agree according to the table below.
+ * <p>
  * The JVM will ensure that on first execution of an {@code ldc} instruction
- * for this entry, a {@link java.dyn.MethodHandle} will be created which represents
+ * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
  * the field or method reference, according to the specific mode implied by the subtag.
  * <p>
  * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
@@ -126,6 +159,129 @@
  * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
  * may force class initialization on their first invocation, just like the corresponding bytecodes.
  *
+ * <h2><a name="bsm"></a>Bootstrap Methods</h2>
+ * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
+ * the call site must first be <em>linked</em>.
+ * Linking is accomplished by calling a <em>bootstrap method</em>
+ * which is given the static information content of the call site,
+ * and which must produce a {@link java.dyn.MethodHandle method handle}
+ * that gives the behavior of the call site.
+ * <p>
+ * Each {@code invokedynamic} instruction statically specifies its own
+ * bootstrap method as a constant pool reference.
+ * The constant pool reference also specifies the call site's name and type signature,
+ * just like {@code invokevirtual} and the other invoke instructions.
+ * <p>
+ * Linking starts with resolving the constant pool entry for the
+ * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
+ * the type signature of the dynamic call site.
+ * This resolution process may trigger class loading.
+ * It may therefore throw an error if a class fails to load.
+ * This error becomes the abnormal termination of the dynamic
+ * call site execution.
+ * Linkage does not trigger class initialization.
+ * <p>
+ * Next, the bootstrap method call is started, with four values being stacked:
+ * <ul>
+ * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
+ * <li>a {@code Class}, the <em>caller class</em> in which dynamic call site occurs </li>
+ * <li>a {@code String}, the method name mentioned in the call site </li>
+ * <li>a {@code MethodType}, the resolved type signature of the call </li>
+ * </ul>
+ * The method handle is then applied to the other values as if by
+ * {@linkplain java.dyn.MethodHandle#invokeGeneric the <code>invokeGeneric</code> method}.
+ * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
+ * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
+ * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
+ * is then called on the returned value.  The result of that second
+ * call is the {@code MethodHandle} which becomes the
+ * permanent binding for the dynamic call site.
+ * That method handle's type must be exactly equal to the type
+ * derived from the dynamic call site signature and passed to
+ * the bootstrap method.
+ * <p>
+ * After resolution, the linkage process may fail in a variety of ways.
+ * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
+ * which is thrown as the abnormal termination of the dynamic call
+ * site execution.
+ * The following circumstances will cause this:
+ * <ul>
+ * <li>the bootstrap method invocation completes abnormally </li>
+ * <li>the result from the bootstrap invocation is not a reference to
+ *     an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider} </li>
+ * <li>the call to {@code asMethodHandle} completes abnormally </li>
+ * <li>the call to {@code asMethodHandle} fails to return a reference to
+ *     an object of type {@link java.dyn.MethodHandle MethodHandle} </li>
+ * <li>the method handle produced by {@code asMethodHandle} does not have
+ *     the expected {@code MethodType} </li>
+ * </ul>
+ * <h3>timing of linkage</h3>
+ * A dynamic call site is linked just before its first execution.
+ * The bootstrap method call implementing the linkage occurs within
+ * a thread that is attempting a first execution.
+ * <p>
+ * If there are several such threads, the JVM picks one thread
+ * and runs the bootstrap method while the others wait for the
+ * invocation to terminate normally or abnormally.
+ * <p>
+ * After a bootstrap method is called and a method handle target
+ * successfully extracted, the JVM attempts to link the instruction
+ * being executed to the target method handle.
+ * This may fail if there has been intervening linkage
+ * or invalidation event for the same instruction.
+ * If such a failure occurs, the dynamic call site must be
+ * re-executed from the beginning, either re-linking it
+ * (if it has been invalidated) or invoking the target
+ * (if it the instruction has been linked by some other means).
+ * <p>
+ * If the instruction is linked successfully, the target method
+ * handle is invoked to complete the instruction execution.
+ * The state of linkage continues until the method containing the
+ * dynamic call site is garbage collected, or the dynamic call site
+ * is invalidated by an explicit request,
+ * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
+ * <p>
+ * In an application which requires dynamic call sites with individually
+ * mutable behaviors, their bootstrap methods should produce distinct
+ * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
+ * <p>
+ * If a class containing {@code invokedynamic} instructions
+ * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
+ * subsequent execution of those {@code invokedynamic} instructions
+ * will require linking.
+ * It is as if they had never been executed in the first place.
+ * (However, invalidation does not cause constant pool entries to be
+ * resolved a second time.)
+ * <p>
+ * Invalidation events and bootstrap method calls for a particular
+ * dynamic call site are globally ordered relative to each other.
+ * When an invokedynamic instruction is invalidated, if there is
+ * simultaneously a bootstrap method invocation in process
+ * (in the same thread or a different thread), the result
+ * eventually returned must not be used to link the call site.
+ * Put another way, when a call site is invalidated, its
+ * subsequent linkage (if any) must be performed by a bootstrap method
+ * call initiated after the invalidation occurred.
+ * <p>
+ * If several threads simultaneously execute a bootstrap method for a single dynamic
+ * call site, the JVM must choose one target object and installs it visibly to
+ * all threads.  Any other bootstrap method calls are allowed to complete, but their
+ * results are ignored, and their dynamic call site invocations proceed with the originally
+ * chosen target object.
+ * <p>
+ * The JVM is free to duplicate dynamic call sites.
+ * This means that, even if a class contains just one {@code invokedynamic}
+ * instruction, its bootstrap method may be executed several times,
+ * once for each duplicate.  Thus, bootstrap method code should not
+ * assume an exclusive one-to-one correspondence between particular occurrences
+ * of {@code invokedynamic} bytecodes in class files and linkage events.
+ * <p>
+ * In principle, each individual execution of an {@code invokedynamic}
+ * instruction could be deemed (by a conforming implementation) to be a separate
+ * duplicate, requiring its own execution of the bootstrap method.
+ * However, implementations are expected to perform code duplication
+ * (if at all) in order to improve performance, not make it worse.
+ *
  * @author John Rose, JSR 292 EG
  */
 
--- a/src/share/classes/java/io/ObjectInputStream.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/io/ObjectInputStream.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -265,7 +265,7 @@
      * object currently being deserialized and descriptor for current class.
      * Null when not during readObject upcall.
      */
-    private CallbackContext curContext;
+    private SerialCallbackContext curContext;
 
     /**
      * Creates an ObjectInputStream that reads from the specified InputStream.
@@ -1798,7 +1798,7 @@
     private void readExternalData(Externalizable obj, ObjectStreamClass desc)
         throws IOException
     {
-        CallbackContext oldContext = curContext;
+        SerialCallbackContext oldContext = curContext;
         curContext = null;
         try {
             boolean blocked = desc.hasBlockExternalData();
@@ -1857,10 +1857,10 @@
                     slotDesc.hasReadObjectMethod() &&
                     handles.lookupException(passHandle) == null)
                 {
-                    CallbackContext oldContext = curContext;
+                    SerialCallbackContext oldContext = curContext;
 
                     try {
-                        curContext = new CallbackContext(obj, slotDesc);
+                        curContext = new SerialCallbackContext(obj, slotDesc);
 
                         bin.setBlockDataMode(true);
                         slotDesc.invokeReadObject(obj, this);
@@ -3505,42 +3505,4 @@
         }
     }
 
-    /**
-     * Context that during upcalls to class-defined readObject methods; holds
-     * object currently being deserialized and descriptor for current class.
-     * This context keeps a boolean state to indicate that defaultReadObject
-     * or readFields has already been invoked with this context or the class's
-     * readObject method has returned; if true, the getObj method throws
-     * NotActiveException.
-     */
-    private static class CallbackContext {
-        private final Object obj;
-        private final ObjectStreamClass desc;
-        private final AtomicBoolean used = new AtomicBoolean();
-
-        public CallbackContext(Object obj, ObjectStreamClass desc) {
-            this.obj = obj;
-            this.desc = desc;
-        }
-
-        public Object getObj() throws NotActiveException {
-            checkAndSetUsed();
-            return obj;
-        }
-
-        public ObjectStreamClass getDesc() {
-            return desc;
-        }
-
-        private void checkAndSetUsed() throws NotActiveException {
-            if (!used.compareAndSet(false, true)) {
-                 throw new NotActiveException(
-                      "not in readObject invocation or fields already read");
-            }
-        }
-
-        public void setUsed() {
-            used.set(true);
-        }
-    }
 }
--- a/src/share/classes/java/io/ObjectOutputStream.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/io/ObjectOutputStream.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
+import java.io.SerialCallbackContext;
 
 /**
  * An ObjectOutputStream writes primitive data types and graphs of Java objects
@@ -191,10 +192,12 @@
     private boolean enableReplace;
 
     // values below valid only during upcalls to writeObject()/writeExternal()
-    /** object currently being serialized */
-    private Object curObj;
-    /** descriptor for current class (null if in writeExternal()) */
-    private ObjectStreamClass curDesc;
+    /**
+     * Context during upcalls to class-defined writeObject methods; holds
+     * object currently being serialized and descriptor for current class.
+     * Null when not during writeObject upcall.
+     */
+    private SerialCallbackContext curContext;
     /** current PutField object */
     private PutFieldImpl curPut;
 
@@ -426,9 +429,11 @@
      *          <code>OutputStream</code>
      */
     public void defaultWriteObject() throws IOException {
-        if (curObj == null || curDesc == null) {
+        if ( curContext == null ) {
             throw new NotActiveException("not in call to writeObject");
         }
+        Object curObj = curContext.getObj();
+        ObjectStreamClass curDesc = curContext.getDesc();
         bout.setBlockDataMode(false);
         defaultWriteFields(curObj, curDesc);
         bout.setBlockDataMode(true);
@@ -446,9 +451,11 @@
      */
     public ObjectOutputStream.PutField putFields() throws IOException {
         if (curPut == null) {
-            if (curObj == null || curDesc == null) {
+            if (curContext == null) {
                 throw new NotActiveException("not in call to writeObject");
             }
+            Object curObj = curContext.getObj();
+            ObjectStreamClass curDesc = curContext.getDesc();
             curPut = new PutFieldImpl(curDesc);
         }
         return curPut;
@@ -1420,17 +1427,15 @@
      * writeExternal() method.
      */
     private void writeExternalData(Externalizable obj) throws IOException {
-        Object oldObj = curObj;
-        ObjectStreamClass oldDesc = curDesc;
         PutFieldImpl oldPut = curPut;
-        curObj = obj;
-        curDesc = null;
         curPut = null;
 
         if (extendedDebugInfo) {
             debugInfoStack.push("writeExternal data");
         }
+        SerialCallbackContext oldContext = curContext;
         try {
+            curContext = null;
             if (protocol == PROTOCOL_VERSION_1) {
                 obj.writeExternal(this);
             } else {
@@ -1440,13 +1445,12 @@
                 bout.writeByte(TC_ENDBLOCKDATA);
             }
         } finally {
+            curContext = oldContext;
             if (extendedDebugInfo) {
                 debugInfoStack.pop();
             }
         }
 
-        curObj = oldObj;
-        curDesc = oldDesc;
         curPut = oldPut;
     }
 
@@ -1461,12 +1465,9 @@
         for (int i = 0; i < slots.length; i++) {
             ObjectStreamClass slotDesc = slots[i].desc;
             if (slotDesc.hasWriteObjectMethod()) {
-                Object oldObj = curObj;
-                ObjectStreamClass oldDesc = curDesc;
                 PutFieldImpl oldPut = curPut;
-                curObj = obj;
-                curDesc = slotDesc;
                 curPut = null;
+                SerialCallbackContext oldContext = curContext;
 
                 if (extendedDebugInfo) {
                     debugInfoStack.push(
@@ -1474,18 +1475,19 @@
                         slotDesc.getName() + "\")");
                 }
                 try {
+                    curContext = new SerialCallbackContext(obj, slotDesc);
                     bout.setBlockDataMode(true);
                     slotDesc.invokeWriteObject(obj, this);
                     bout.setBlockDataMode(false);
                     bout.writeByte(TC_ENDBLOCKDATA);
                 } finally {
+                    curContext.setUsed();
+                    curContext = oldContext;
                     if (extendedDebugInfo) {
                         debugInfoStack.pop();
                     }
                 }
 
-                curObj = oldObj;
-                curDesc = oldDesc;
                 curPut = oldPut;
             } else {
                 defaultWriteFields(obj, slotDesc);
--- a/src/share/classes/java/io/ObjectStreamClass.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/io/ObjectStreamClass.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -1830,8 +1830,10 @@
         private final ObjectStreamField[] fields;
         /** number of primitive fields */
         private final int numPrimFields;
-        /** unsafe field keys */
-        private final long[] keys;
+        /** unsafe field keys for reading fields - may contain dupes */
+        private final long[] readKeys;
+        /** unsafe fields keys for writing fields - no dupes */
+        private final long[] writeKeys;
         /** field data offsets */
         private final int[] offsets;
         /** field type codes */
@@ -1849,16 +1851,22 @@
         FieldReflector(ObjectStreamField[] fields) {
             this.fields = fields;
             int nfields = fields.length;
-            keys = new long[nfields];
+            readKeys = new long[nfields];
+            writeKeys = new long[nfields];
             offsets = new int[nfields];
             typeCodes = new char[nfields];
             ArrayList<Class<?>> typeList = new ArrayList<Class<?>>();
+            Set<Long> usedKeys = new HashSet<Long>();
+
 
             for (int i = 0; i < nfields; i++) {
                 ObjectStreamField f = fields[i];
                 Field rf = f.getField();
-                keys[i] = (rf != null) ?
+                long key = (rf != null) ?
                     unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
+                readKeys[i] = key;
+                writeKeys[i] = usedKeys.add(key) ?
+                    key : Unsafe.INVALID_FIELD_OFFSET;
                 offsets[i] = f.getOffset();
                 typeCodes[i] = f.getTypeCode();
                 if (!f.isPrimitive()) {
@@ -1894,7 +1902,7 @@
              * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
              */
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = readKeys[i];
                 int off = offsets[i];
                 switch (typeCodes[i]) {
                     case 'Z':
@@ -1945,7 +1953,7 @@
                 throw new NullPointerException();
             }
             for (int i = 0; i < numPrimFields; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
@@ -2006,7 +2014,7 @@
                 switch (typeCodes[i]) {
                     case 'L':
                     case '[':
-                        vals[offsets[i]] = unsafe.getObject(obj, keys[i]);
+                        vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
                         break;
 
                     default:
@@ -2027,7 +2035,7 @@
                 throw new NullPointerException();
             }
             for (int i = numPrimFields; i < fields.length; i++) {
-                long key = keys[i];
+                long key = writeKeys[i];
                 if (key == Unsafe.INVALID_FIELD_OFFSET) {
                     continue;           // discard value
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/io/SerialCallbackContext.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,58 @@
+  /*
+   * %W% %E%
+   *
+   * Copyright (c) 2006, 2010  Oracle and/or its affiliates. All rights reserved.
+   * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+   */
+
+  package java.io;
+
+  /**
+   * Context during upcalls from object stream to class-defined
+   * readObject/writeObject methods.
+   * Holds object currently being deserialized and descriptor for current class.
+   *
+   * This context keeps track of the thread it was constructed on, and allows
+   * only a single call of defaultReadObject, readFields, defaultWriteObject
+   * or writeFields which must be invoked on the same thread before the class's
+   * readObject/writeObject method has returned.
+   * If not set to the current thread, the getObj method throws NotActiveException.
+   */
+  final class SerialCallbackContext {
+      private final Object obj;
+      private final ObjectStreamClass desc;
+      /**
+       * Thread this context is in use by.
+       * As this only works in one thread, we do not need to worry about thread-safety.
+       */
+      private Thread thread;
+
+      public SerialCallbackContext(Object obj, ObjectStreamClass desc) {
+          this.obj = obj;
+          this.desc = desc;
+          this.thread = Thread.currentThread();
+      }
+
+      public Object getObj() throws NotActiveException {
+          checkAndSetUsed();
+          return obj;
+      }
+
+      public ObjectStreamClass getDesc() {
+          return desc;
+      }
+
+      private void checkAndSetUsed() throws NotActiveException {
+          if (thread != Thread.currentThread()) {
+               throw new NotActiveException(
+                "not in readObject invocation or fields already read");
+          }
+          thread = null;
+      }
+
+      public void setUsed() {
+          thread = null;
+      }
+  }
+
+
--- a/src/share/classes/java/io/package.html	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/io/package.html	Thu Nov 18 10:35:46 2010 -0800
@@ -44,7 +44,7 @@
 For overviews, tutorials, examples, guides, and tool documentation,
 please see:
 <ul>
-  <li><a href="../../../guide/serialization">Serialization Enhancements</a>
+  <li><a href="../../../technotes/guides/serialization">Serialization Enhancements</a>
 </ul>
 
 @since JDK1.0
--- a/src/share/classes/java/lang/AbstractStringBuilder.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java	Thu Nov 18 10:35:46 2010 -0800
@@ -100,7 +100,8 @@
      * @param   minimumCapacity   the minimum desired capacity.
      */
     public void ensureCapacity(int minimumCapacity) {
-        ensureCapacityInternal(minimumCapacity);
+        if (minimumCapacity > 0)
+            ensureCapacityInternal(minimumCapacity);
     }
 
     /**
@@ -108,6 +109,7 @@
      * never synchronized.
      */
     private void ensureCapacityInternal(int minimumCapacity) {
+        // overflow-conscious code
         if (minimumCapacity - value.length > 0)
             expandCapacity(minimumCapacity);
     }
--- a/src/share/classes/java/lang/ClassLoader.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/lang/ClassLoader.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2010, 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
@@ -100,8 +100,11 @@
  * themselves at their class initialization time by invoking the
  * {@link
  * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
- * method. In environments in which the delegation model is not strictly
- * hierarchical, class loaders need to be parallel capable, otherise class
+ * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
+ * capable by default. However, its subclasses still need to register themselves
+ * if they are parallel capable. <br>
+ * In environments in which the delegation model is not strictly
+ * hierarchical, class loaders need to be parallel capable, otherwise class
  * loading can lead to deadlocks because the loader lock is held for the
  * duration of the class loading process (see {@link #loadClass
  * <tt>loadClass</tt>} methods).
@@ -550,6 +553,13 @@
      *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
      *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
      *
+     * @throws  SecurityException
+     *          If an attempt is made to add this class to a package that
+     *          contains classes that were signed by a different set of
+     *          certificates than this class, or if an attempt is made
+     *          to define a class in a package with a fully-qualified name
+     *          that starts with "{@code java.}".
+     *
      * @see  #loadClass(String, boolean)
      * @see  #resolveClass(Class)
      *
@@ -1218,14 +1228,14 @@
     private static native Class<? extends ClassLoader> getCaller(int index);
 
     /**
-     * Registers the caller class loader as parallel capable.
-     * In order for the registration to succeed, all super classes
-     * of the caller class loader must also be registered as
-     * parallel capable when this method is called. </p>
-     * Note that once a class loader is registered as
-     * parallel capable, there is no way to change it back.
-     * In addition, registration should be done statically before
-     * any instance of the caller classloader being constructed. </p>
+     * Registers the caller as parallel capable.</p>
+     * The registration succeeds if and only if all of the following
+     * conditions are met: <br>
+     * 1. no instance of the caller has been created</p>
+     * 2. all of the super classes (except class Object) of the caller are
+     * registered as parallel capable</p>
+     * Note that once a class loader is registered as parallel capable, there
+     * is no way to change it back. </p>
      *
      * @return  true if the caller is successfully registered as
      *          parallel capable and false if otherwise.
--- a/src/share/classes/java/lang/Integer.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/lang/Integer.java	Thu Nov 18 10:35:46 2010 -0800
@@ -586,25 +586,13 @@
      * Cache to support the object identity semantics of autoboxing for values between
      * -128 and 127 (inclusive) as required by JLS.
      *
-     * The cache is initialized on first usage. During VM initialization the
-     * getAndRemoveCacheProperties method may be used to get and remove any system
-     * properites that configure the cache size. At this time, the size of the
-     * cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
+     * The cache is initialized on first usage.  The size of the cache
+     * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
+     * During VM initialization, java.lang.Integer.IntegerCache.high property
+     * may be set and saved in the private system properties in the
+     * sun.misc.VM class.
      */
 
-    // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
-    private static String integerCacheHighPropValue;
-
-    static void getAndRemoveCacheProperties() {
-        if (!sun.misc.VM.isBooted()) {
-            Properties props = System.getProperties();
-            integerCacheHighPropValue =
-                (String)props.remove("java.lang.Integer.IntegerCache.high");
-            if (integerCacheHighPropValue != null)
-                System.setProperties(props);  // remove from system props
-        }
-    }
-
     private static class IntegerCache {
         static final int low = -128;
         static final int high;
@@ -613,6 +601,8 @@
         static {
             // high value may be configured by property
             int h = 127;
+            String integerCacheHighPropValue =
+                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
             if (integerCacheHighPropValue != null) {
                 int i = parseInt(integerCacheHighPropValue);
                 i = Math.max(i, 127);
--- a/src/share/classes/java/lang/LinkageError.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/lang/LinkageError.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
 package java.lang;
 
 /**
- * Subclasses of <code>LinkageError</code> indicate that a class has
+ * Subclasses of {@code LinkageError} indicate that a class has
  * some dependency on another class; however, the latter class has
  * incompatibly changed after the compilation of the former class.
  *
@@ -39,14 +39,14 @@
     private static final long serialVersionUID = 3579600108157160122L;
 
     /**
-     * Constructs a <code>LinkageError</code> with no detail message.
+     * Constructs a {@code LinkageError} with no detail message.
      */
     public LinkageError() {
         super();
     }
 
     /**
-     * Constructs a <code>LinkageError</code> with the specified detail
+     * Constructs a {@code LinkageError} with the specified detail
      * message.
      *
      * @param   s   the detail message.
@@ -54,4 +54,16 @@
     public LinkageError(String s) {
         super(s);
     }
+
+    /**
+     * Constructs a {@code LinkageError} with the specified detail
+     * message and cause.
+     *
+     * @param s     the detail message.
+     * @param cause the cause, may be {@code null}
+     * @since 1.7
+     */
+    public LinkageError(String s, Throwable cause) {
+        super(s, cause);
+    }
 }
--- a/src/share/classes/java/lang/System.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/lang/System.java	Thu Nov 18 10:35:46 2010 -0800
@@ -53,7 +53,13 @@
  */
 public final class System {
 
-    /* First thing---register the natives */
+    /* register the natives via the static initializer.
+     *
+     * VM will invoke the initializeSystemClass method to complete
+     * the initialization for this class separated from clinit.
+     * Note that to use properties set by the VM, see the constraints
+     * described in the initializeSystemClass method.
+     */
     private static native void registerNatives();
     static {
         registerNatives();
@@ -1096,17 +1102,21 @@
      * Initialize the system class.  Called after thread initialization.
      */
     private static void initializeSystemClass() {
-        props = new Properties();
-        initProperties(props);
+        // There are certain system configurations that may be controlled by
+        // VM options such as the maximum amount of direct memory and
+        // Integer cache size used to support the object identity semantics
+        // of autoboxing.  Typically, the library will obtain these values
+        // from the properties set by the VM.  If the properties are for
+        // internal implementation use only, these properties should be
+        // removed from the system properties.
+        //
+        // See java.lang.Integer.IntegerCache and the
+        // sun.misc.VM.saveAndRemoveProperties method for example.
+        props = initSystemProperties();
+
         lineSeparator = props.getProperty("line.separator");
         sun.misc.Version.init();
 
-        // Gets and removes system properties that configure the Integer
-        // cache used to support the object identity semantics of autoboxing.
-        // At this time, the size of the cache may be controlled by the
-        // vm option -XX:AutoBoxCacheMax=<size>.
-        Integer.getAndRemoveCacheProperties();
-
         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
         FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
         FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
@@ -1127,17 +1137,6 @@
         // classes are used.
         sun.misc.VM.initializeOSEnvironment();
 
-        // Set the maximum amount of direct memory.  This value is controlled
-        // by the vm option -XX:MaxDirectMemorySize=<size>.  This method acts
-        // as an initializer only if it is called before sun.misc.VM.booted().
-        sun.misc.VM.maxDirectMemory();
-
-        // Set a boolean to determine whether ClassLoader.loadClass accepts
-        // array syntax.  This value is controlled by the system property
-        // "sun.lang.ClassLoader.allowArraySyntax".  This method acts as
-        // an initializer only if it is called before sun.misc.VM.booted().
-        sun.misc.VM.allowArraySyntax();
-
         // Subsystems that are invoked during initialization can invoke
         // sun.misc.VM.isBooted() in order to avoid doing things that should
         // wait until the application class loader has been set up.
@@ -1152,6 +1151,18 @@
         setJavaLangAccess();
     }
 
+    private static Properties initSystemProperties() {
+        Properties props = new Properties();
+        initProperties(props);  // initialized by the VM
+
+        // Save a private copy of the system properties object that
+        // can only be accessed by the internal implementation.  Remove
+        // certain system properties that are not intended for public access.
+        sun.misc.VM.saveAndRemoveProperties(props);
+
+        return props;
+    }
+
     private static void setJavaLangAccess() {
         // Allow privileged classes outside of java.lang
         sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
--- a/src/share/classes/java/net/AbstractPlainSocketImpl.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Nov 18 10:35:46 2010 -0800
@@ -28,9 +28,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.InterruptedIOException;
 import java.io.FileDescriptor;
-import java.io.ByteArrayOutputStream;
 
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
@@ -58,7 +56,7 @@
     protected int fdUseCount = 0;
 
     /* lock when increment/decrementing fdUseCount */
-    protected Object fdLock = new Object();
+    protected final Object fdLock = new Object();
 
     /* indicates a close is pending on the file descriptor */
     protected boolean closePending = false;
@@ -68,7 +66,7 @@
     private int CONNECTION_RESET_PENDING = 1;
     private int CONNECTION_RESET = 2;
     private int resetState;
-    private Object resetLock = new Object();
+    private final Object resetLock = new Object();
 
     /**
      * Load net library into runtime.
@@ -100,25 +98,24 @@
     protected void connect(String host, int port)
         throws UnknownHostException, IOException
     {
-        IOException pending = null;
+        boolean connected = false;
         try {
             InetAddress address = InetAddress.getByName(host);
             this.port = port;
             this.address = address;
 
-            try {
-                connectToAddress(address, port, timeout);
-                return;
-            } catch (IOException e) {
-                pending = e;
+            connectToAddress(address, port, timeout);
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
             }
-        } catch (UnknownHostException e) {
-            pending = e;
         }
-
-        // everything failed
-        close();
-        throw pending;
     }
 
     /**
@@ -151,22 +148,29 @@
      *          SocketAddress subclass not supported by this socket
      * @since 1.4
      */
-    protected void connect(SocketAddress address, int timeout) throws IOException {
-        if (address == null || !(address instanceof InetSocketAddress))
-            throw new IllegalArgumentException("unsupported address type");
-        InetSocketAddress addr = (InetSocketAddress) address;
-        if (addr.isUnresolved())
-            throw new UnknownHostException(addr.getHostName());
-        this.port = addr.getPort();
-        this.address = addr.getAddress();
+    protected void connect(SocketAddress address, int timeout)
+            throws IOException {
+        boolean connected = false;
+        try {
+            if (address == null || !(address instanceof InetSocketAddress))
+                throw new IllegalArgumentException("unsupported address type");
+            InetSocketAddress addr = (InetSocketAddress) address;
+            if (addr.isUnresolved())
+                throw new UnknownHostException(addr.getHostName());
+            this.port = addr.getPort();
+            this.address = addr.getAddress();
 
-        try {
             connectToAddress(this.address, port, timeout);
-            return;
-        } catch (IOException e) {
-            // everything failed
-            close();
-            throw e;
+            connected = true;
+        } finally {
+            if (!connected) {
+                try {
+                    close();
+                } catch (IOException ioe) {
+                    /* Do nothing. If connect threw an exception then
+                       it will be passed up the call stack */
+                }
+            }
         }
     }
 
@@ -311,7 +315,7 @@
             }
         }
         try {
-            FileDescriptor fd = acquireFD();
+            acquireFD();
             try {
                 socketConnect(address, port, timeout);
                 /* socket may have been closed during poll/select */
@@ -370,7 +374,7 @@
      * @param s the connection
      */
     protected void accept(SocketImpl s) throws IOException {
-        FileDescriptor fd = acquireFD();
+        acquireFD();
         try {
             socketAccept(s);
         } finally {
@@ -562,7 +566,6 @@
         close();
     }
 
-
     /*
      * "Acquires" and returns the FileDescriptor for this impl
      *
--- a/src/share/classes/java/net/HttpURLConnection.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/net/HttpURLConnection.java	Thu Nov 18 10:35:46 2010 -0800
@@ -399,6 +399,8 @@
      * @param method the HTTP method
      * @exception ProtocolException if the method cannot be reset or if
      *              the requested method isn't valid for HTTP.
+     * @exception SecurityException if a security manager is set and the
+     *              "allowHttpTrace" NetPermission is not granted.
      * @see #getRequestMethod()
      */
     public void setRequestMethod(String method) throws ProtocolException {
@@ -412,6 +414,12 @@
 
         for (int i = 0; i < methods.length; i++) {
             if (methods[i].equals(method)) {
+                if (method.equals("TRACE")) {
+                    SecurityManager s = System.getSecurityManager();
+                    if (s != null) {
+                        s.checkPermission(new NetPermission("allowHttpTrace"));
+                    }
+                }
                 this.method = method;
                 return;
             }
--- a/src/share/classes/java/net/NetPermission.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/net/NetPermission.java	Thu Nov 18 10:35:46 2010 -0800
@@ -54,44 +54,23 @@
  * <th>What the Permission Allows</th>
  * <th>Risks of Allowing this Permission</th>
  * </tr>
+ * <tr>
+ *   <td>allowHttpTrace</td>
+ *   <td>The ability to use the HTTP TRACE method in HttpURLConnection.</td>
+ *   <td>Malicious code using HTTP TRACE could get access to security sensitive
+ *   information in the HTTP headers (such as cookies) that it might not
+ *   otherwise have access to.</td>
+ *   </tr>
  *
  * <tr>
- *   <td>setDefaultAuthenticator</td>
- *   <td>The ability to set the
- * way authentication information is retrieved when
- * a proxy or HTTP server asks for authentication</td>
- *   <td>Malicious
- * code can set an authenticator that monitors and steals user
- * authentication input as it retrieves the input from the user.</td>
- * </tr>
- *
- * <tr>
- *   <td>requestPasswordAuthentication</td>
- *   <td>The ability
- * to ask the authenticator registered with the system for
- * a password</td>
- *   <td>Malicious code may steal this password.</td>
- * </tr>
- *
- * <tr>
- *   <td>specifyStreamHandler</td>
- *   <td>The ability
- * to specify a stream handler when constructing a URL</td>
- *   <td>Malicious code may create a URL with resources that it would
-normally not have access to (like file:/foo/fum/), specifying a
-stream handler that gets the actual bytes from someplace it does
-have access to. Thus it might be able to trick the system into
-creating a ProtectionDomain/CodeSource for a class even though
-that class really didn't come from that location.</td>
- * </tr>
- *
- * <tr>
- *   <td>setProxySelector</td>
- *   <td>The ability to set the proxy selector used to make decisions
- *   on which proxies to use when making network connections.</td>
- *   <td>Malicious code can set a ProxySelector that directs network
- *   traffic to an arbitrary network host.</td>
- * </tr>
+ *   <td>getCookieHandler</td>
+ *   <td>The ability to get the cookie handler that processes highly
+ *   security sensitive cookie information for an Http session.</td>
+ *   <td>Malicious code can get a cookie handler to obtain access to
+ *   highly security sensitive cookie information. Some web servers
+ *   use cookies to save user private information such as access
+ *   control information, or to track user browsing habit.</td>
+ *   </tr>
  *
  * <tr>
  *   <td>getProxySelector</td>
@@ -103,6 +82,22 @@
  * </tr>
  *
  * <tr>
+ *   <td>getResponseCache</td>
+ *   <td>The ability to get the response cache that provides
+ *   access to a local response cache.</td>
+ *   <td>Malicious code getting access to the local response cache
+ *   could access security sensitive information.</td>
+ *   </tr>
+ *
+ * <tr>
+ *   <td>requestPasswordAuthentication</td>
+ *   <td>The ability
+ * to ask the authenticator registered with the system for
+ * a password</td>
+ *   <td>Malicious code may steal this password.</td>
+ * </tr>
+ *
+ * <tr>
  *   <td>setCookieHandler</td>
  *   <td>The ability to set the cookie handler that processes highly
  *   security sensitive cookie information for an Http session.</td>
@@ -113,14 +108,22 @@
  *   </tr>
  *
  * <tr>
- *   <td>getCookieHandler</td>
- *   <td>The ability to get the cookie handler that processes highly
- *   security sensitive cookie information for an Http session.</td>
- *   <td>Malicious code can get a cookie handler to obtain access to
- *   highly security sensitive cookie information. Some web servers
- *   use cookies to save user private information such as access
- *   control information, or to track user browsing habit.</td>
- *   </tr>
+ *   <td>setDefaultAuthenticator</td>
+ *   <td>The ability to set the
+ * way authentication information is retrieved when
+ * a proxy or HTTP server asks for authentication</td>
+ *   <td>Malicious
+ * code can set an authenticator that monitors and steals user
+ * authentication input as it retrieves the input from the user.</td>
+ * </tr>
+ *
+ * <tr>
+ *   <td>setProxySelector</td>
+ *   <td>The ability to set the proxy selector used to make decisions
+ *   on which proxies to use when making network connections.</td>
+ *   <td>Malicious code can set a ProxySelector that directs network
+ *   traffic to an arbitrary network host.</td>
+ * </tr>
  *
  * <tr>
  *   <td>setResponseCache</td>
@@ -132,13 +135,16 @@
  *   </tr>
  *
  * <tr>
- *   <td>getResponseCache</td>
- *   <td>The ability to get the response cache that provides
- *   access to a local response cache.</td>
- *   <td>Malicious code getting access to the local response cache
- *   could access security sensitive information.</td>
- *   </tr>
- *
+ *   <td>specifyStreamHandler</td>
+ *   <td>The ability
+ * to specify a stream handler when constructing a URL</td>
+ *   <td>Malicious code may create a URL with resources that it would
+normally not have access to (like file:/foo/fum/), specifying a
+stream handler that gets the actual bytes from someplace it does
+have access to. Thus it might be able to trick the system into
+creating a ProtectionDomain/CodeSource for a class even though
+that class really didn't come from that location.</td>
+ * </tr>
  * </table>
  *
  * @see java.security.BasicPermission
--- a/src/share/classes/java/net/NetworkInterface.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/net/NetworkInterface.java	Thu Nov 18 10:35:46 2010 -0800
@@ -86,7 +86,9 @@
      * If there is a security manager, its <code>checkConnect</code>
      * method is called for each InetAddress. Only InetAddresses where
      * the <code>checkConnect</code> doesn't throw a SecurityException
-     * will be returned in the Enumeration.
+     * will be returned in the Enumeration. However, if the caller has the
+     * {@link NetPermission}("getNetworkInformation") permission, then all
+     * InetAddresses are returned.
      * @return an Enumeration object with all or a subset of the InetAddresses
      * bound to this network interface
      */
@@ -99,11 +101,19 @@
 
             checkedAddresses() {
                 local_addrs = new InetAddress[addrs.length];
+                boolean trusted = true;
 
                 SecurityManager sec = System.getSecurityManager();
+                if (sec != null) {
+                    try {
+                        sec.checkPermission(new NetPermission("getNetworkInformation"));
+                    } catch (SecurityException e) {
+                        trusted = false;
+                    }
+                }
                 for (int j=0; j<addrs.length; j++) {
                     try {
-                        if (sec != null) {
+                        if (sec != null && !trusted) {
                             sec.checkConnect(addrs[j].getHostAddress(), -1);
                         }
                         local_addrs[count++] = addrs[j];
@@ -402,13 +412,29 @@
     /**
      * Returns the hardware address (usually MAC) of the interface if it
      * has one and if it can be accessed given the current privileges.
+     * If a security manager is set, then the caller must have
+     * the permission {@link NetPermission}("getNetworkInformation").
      *
-     * @return  a byte array containing the address or <code>null</code> if
-     *          the address doesn't exist or is not accessible.
+     * @return  a byte array containing the address, or <code>null</code> if
+     *          the address doesn't exist, is not accessible or a security
+     *          manager is set and the caller does not have the permission
+     *          NetPermission("getNetworkInformation")
+     *
      * @exception       SocketException if an I/O error occurs.
      * @since 1.6
      */
     public byte[] getHardwareAddress() throws SocketException {
+        SecurityManager sec = System.getSecurityManager();
+        if (sec != null) {
+            try {
+                sec.checkPermission(new NetPermission("getNetworkInformation"));
+            } catch (SecurityException e) {
+                if (!getInetAddresses().hasMoreElements()) {
+                    // don't have connect permission to any local address
+                    return null;
+                }
+            }
+        }
         for (InetAddress addr : addrs) {
             if (addr instanceof Inet4Address) {
                 return getMacAddr0(((Inet4Address)addr).getAddress(), name, index);
@@ -523,11 +549,10 @@
     }
 
     public int hashCode() {
-        int count = 0;
-        if (addrs != null) {
-            for (int i = 0; i < addrs.length; i++) {
-                count += addrs[i].hashCode();
-            }
+        int count = name == null? 0: name.hashCode();
+        Enumeration<InetAddress> addrs = getInetAddresses();
+        while (addrs.hasMoreElements()) {
+            count += addrs.nextElement().hashCode();
         }
         return count;
     }
--- a/src/share/classes/java/nio/Bits.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/nio/Bits.java	Thu Nov 18 10:35:46 2010 -0800
@@ -622,7 +622,7 @@
     // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
     private static volatile long maxMemory = VM.maxDirectMemory();
     private static volatile long reservedMemory;
-    private static volatile long usedMemory;
+    private static volatile long totalCapacity;
     private static volatile long count;
     private static boolean memoryLimitSet = false;
 
@@ -630,15 +630,17 @@
     // freed.  They allow the user to control the amount of direct memory
     // which a process may access.  All sizes are specified in bytes.
     static void reserveMemory(long size, int cap) {
-
         synchronized (Bits.class) {
             if (!memoryLimitSet && VM.isBooted()) {
                 maxMemory = VM.maxDirectMemory();
                 memoryLimitSet = true;
             }
-            if (size <= maxMemory - reservedMemory) {
+            // -XX:MaxDirectMemorySize limits the total capacity rather than the
+            // actual memory usage, which will differ when buffers are page
+            // aligned.
+            if (cap <= maxMemory - totalCapacity) {
                 reservedMemory += size;
-                usedMemory += cap;
+                totalCapacity += cap;
                 count++;
                 return;
             }
@@ -652,10 +654,10 @@
             Thread.currentThread().interrupt();
         }
         synchronized (Bits.class) {
-            if (reservedMemory + size > maxMemory)
+            if (totalCapacity + cap > maxMemory)
                 throw new OutOfMemoryError("Direct buffer memory");
             reservedMemory += size;
-            usedMemory += cap;
+            totalCapacity += cap;
             count++;
         }
 
@@ -664,7 +666,7 @@
     static synchronized void unreserveMemory(long size, int cap) {
         if (reservedMemory > 0) {
             reservedMemory -= size;
-            usedMemory -= cap;
+            totalCapacity -= cap;
             count--;
             assert (reservedMemory > -1);
         }
@@ -689,7 +691,7 @@
                         }
                         @Override
                         public long getTotalCapacity() {
-                            return Bits.usedMemory;
+                            return Bits.totalCapacity;
                         }
                         @Override
                         public long getMemoryUsed() {
--- a/src/share/classes/java/nio/Direct-X-Buffer.java.template	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Nov 18 10:35:46 2010 -0800
@@ -27,8 +27,10 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Cleaner;
 import sun.misc.Unsafe;
+import sun.misc.VM;
 import sun.nio.ch.DirectBuffer;
 
 
@@ -113,9 +115,10 @@
     //
     Direct$Type$Buffer$RW$(int cap) {                   // package-private
 #if[rw]
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
+        boolean pa = VM.isDirectMemoryPageAligned();
         int ps = Bits.pageSize();
-        int size = cap + ps;
+        long size = Math.max(1L, (long)cap + (pa ? ps : 0));
         Bits.reserveMemory(size, cap);
 
         long base = 0;
@@ -126,7 +129,7 @@
             throw x;
         }
         unsafe.setMemory(base, size, (byte) 0);
-        if (base % ps != 0) {
+        if (pa && (base % ps != 0)) {
             // Round up to page boundary
             address = base + ps - (base & (ps - 1));
         } else {
@@ -143,7 +146,7 @@
     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
     //
     private Direct$Type$Buffer(long addr, int cap) {
-        super(-1, 0, cap, cap, false);
+        super(-1, 0, cap, cap);
         address = addr;
         cleaner = null;
     }
@@ -152,14 +155,17 @@
 
     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
     //
-    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+    protected Direct$Type$Buffer$RW$(int cap, long addr,
+                                     FileDescriptor fd,
+                                     Runnable unmapper)
+    {
 #if[rw]
-        super(-1, 0, cap, cap, true);
+        super(-1, 0, cap, cap, fd);
         address = addr;
         viewedBuffer = null;
         cleaner = Cleaner.create(this, unmapper);
 #else[rw]
-        super(cap, addr, unmapper);
+        super(cap, addr, fd, unmapper);
 #end[rw]
     }
 
--- a/src/share/classes/java/nio/MappedByteBuffer.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/nio/MappedByteBuffer.java	Thu Nov 18 10:35:46 2010 -0800
@@ -25,6 +25,7 @@
 
 package java.nio;
 
+import java.io.FileDescriptor;
 import sun.misc.Unsafe;
 
 
@@ -71,26 +72,26 @@
     // for optimization purposes, it's easier to do it the other way around.
     // This works because DirectByteBuffer is a package-private class.
 
-    // Volatile to make sure that the finalization thread sees the current
-    // value of this so that a region is not accidentally unmapped again later.
-    volatile boolean isAMappedBuffer;                   // package-private
+    // For mapped buffers, a FileDescriptor that may be used for mapping
+    // operations if valid; null if the buffer is not mapped.
+    private final FileDescriptor fd;
 
     // This should only be invoked by the DirectByteBuffer constructors
     //
     MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
-                     boolean mapped)
+                     FileDescriptor fd)
     {
         super(mark, pos, lim, cap);
-        isAMappedBuffer = mapped;
+        this.fd = fd;
     }
 
     MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
         super(mark, pos, lim, cap);
-        isAMappedBuffer = false;
+        this.fd = null;
     }
 
     private void checkMapped() {
-        if (!isAMappedBuffer)
+        if (fd == null)
             // Can only happen if a luser explicitly casts a direct byte buffer
             throw new UnsupportedOperationException();
     }
@@ -191,13 +192,12 @@
         checkMapped();
         if ((address != 0) && (capacity() != 0)) {
             long offset = mappingOffset();
-            force0(mappingAddress(offset), mappingLength(offset));
+            force0(fd, mappingAddress(offset), mappingLength(offset));
         }
         return this;
     }
 
     private native boolean isLoaded0(long address, long length, int pageCount);
     private native void load0(long address, long length);
-    private native void force0(long address, long length);
-
+    private native void force0(FileDescriptor fd, long address, long length);
 }
--- a/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java	Fri Oct 22 14:14:54 2010 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-/*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.nio.channels;
-
-import java.nio.channels.spi.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.Future;
-import java.io.IOException;
-import java.net.SocketOption;
-import java.net.SocketAddress;
-import java.net.ProtocolFamily;
-import java.nio.ByteBuffer;
-
-/**
- * An asynchronous channel for datagram-oriented sockets.
- *
- * <p> An asynchronous datagram channel is created by invoking one of the {@link
- * #open open} methods defined by this class. It is not possible to create a channel
- * for an arbitrary, pre-existing datagram socket. A newly-created asynchronous
- * datagram channel is open but not connected. It need not be connected in order
- * for the {@link #send send} and {@link #receive receive} methods to be used.
- * A datagram channel may be connected, by invoking its {@link #connect connect}
- * method, in order to avoid the overhead of the security checks that are otherwise
- * performed as part of every send and receive operation when a security manager
- * is set. The channel must be connected in order to use the {@link #read read}
- * and {@link #write write} methods, since those methods do not accept or return
- * socket addresses. Once connected, an asynchronous datagram channel remains
- * connected until it is disconnected or closed.
- *
- * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
- * setOption} method. An asynchronous datagram channel to an Internet Protocol
- * (IP) socket supports the following options:
- * <blockquote>
- * <table border>
- *   <tr>
- *     <th>Option Name</th>
- *     <th>Description</th>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
- *     <td> The size of the socket send buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
- *     <td> The size of the socket receive buffer </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
- *     <td> Re-use address </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
- *     <td> Allow transmission of broadcast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
- *     <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
- *     <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
- *       IP_MULTICAST_TTL} </td>
- *     <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
- *       datagrams </td>
- *   </tr>
- *   <tr>
- *     <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
- *       IP_MULTICAST_LOOP} </td>
- *     <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
- *   </tr>
- * </table>
- * </blockquote>
- * Additional (implementation specific) options may also be supported.
- *
- * <p> Asynchronous datagram channels allow more than one read/receive and
- * write/send to be oustanding at any given time.
- *
- * <p> <b>Usage Example:</b>
- * <pre>
- *  final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
- *      .bind(new InetSocketAddress(4000));
- *
- *  // print the source address of all packets that we receive
- *  dc.receive(buffer, buffer, new CompletionHandler&lt;SocketAddress,ByteBuffer&gt;() {
- *      public void completed(SocketAddress sa, ByteBuffer buffer) {
- *          System.out.println(sa);
- *          buffer.clear();
- *          dc.receive(buffer, buffer, this);
- *      }
- *      public void failed(Throwable exc, ByteBuffer buffer) {
- *          ...
- *      }
- *  });
- * </pre>
- *
- * @since 1.7
- */
-
-public abstract class AsynchronousDatagramChannel
-    implements AsynchronousByteChannel, MulticastChannel
-{
-    private final AsynchronousChannelProvider provider;
-
-    /**
-     * Initializes a new instance of this class.
-     */
-    protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) {
-        this.provider = provider;
-    }
-
-    /**
-     * Returns the provider that created this channel.
-     */
-    public final AsynchronousChannelProvider provider() {
-        return provider;
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> The new channel is created by invoking the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel
-     * openAsynchronousDatagramChannel} method on the {@link
-     * java.nio.channels.spi.AsynchronousChannelProvider} object that created
-     * the given group (or the default provider where {@code group} is {@code
-     * null}).
-     *
-     * <p> The {@code family} parameter is used to specify the {@link ProtocolFamily}.
-     * If the datagram channel is to be used for Internet Protocol {@link
-     * MulticastChannel multicasting} then this parameter should correspond to
-     * the address type of the multicast groups that this channel will join.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} to use the default protocol
-     *          family
-     * @param   group
-     *          The group to which the newly constructed channel should be bound,
-     *          or {@code null} for the default group
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  UnsupportedOperationException
-     *          If the specified protocol family is not supported. For example,
-     *          suppose the parameter is specified as {@link
-     *          java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not
-     *          enabled on the platform.
-     * @throws  ShutdownChannelGroupException
-     *          The specified group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open(ProtocolFamily family,
-                                                   AsynchronousChannelGroup group)
-        throws IOException
-    {
-        AsynchronousChannelProvider provider = (group == null) ?
-            AsynchronousChannelProvider.provider() : group.provider();
-        return provider.openAsynchronousDatagramChannel(family, group);
-    }
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * <p> This method returns an asynchronous datagram channel that is
-     * bound to the <em>default group</em>. This method is equivalent to evaluating
-     * the expression:
-     * <blockquote><pre>
-     * open((ProtocolFamily)null,&nbsp;(AsynchronousChannelGroup)null);
-     * </pre></blockquote>
-     *
-     * @return  A new asynchronous datagram channel
-     *
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public static AsynchronousDatagramChannel open()
-        throws IOException
-    {
-        return open(null, null);
-    }
-
-    // -- Socket-specific operations --
-
-    /**
-     * @throws  AlreadyBoundException               {@inheritDoc}
-     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
-     * @throws  ClosedChannelException              {@inheritDoc}
-     * @throws  IOException                         {@inheritDoc}
-     * @throws  SecurityException
-     *          If a security manager has been installed and its {@link
-     *          SecurityManager#checkListen checkListen} method denies the
-     *          operation
-     */
-    @Override
-    public abstract AsynchronousDatagramChannel bind(SocketAddress local)
-        throws IOException;
-
-    /**
-     * @throws  IllegalArgumentException                {@inheritDoc}
-     * @throws  ClosedChannelException                  {@inheritDoc}
-     * @throws  IOException                             {@inheritDoc}
-     */
-    @Override
-    public abstract <T> AsynchronousDatagramChannel setOption(SocketOption<T> name, T value)
-        throws IOException;
-
-    /**
-     * Returns the remote address to which this channel is connected.
-     *
-     * <p> Where the channel is connected to an Internet Protocol socket address
-     * then the return value from this method is of type {@link
-     * java.net.InetSocketAddress}.
-     *
-     * @return  The remote address; {@code null} if the channel's socket is not
-     *          connected
-     *
-     * @throws  ClosedChannelException
-     *          If the channel is closed
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract SocketAddress getRemoteAddress() throws IOException;
-
-    /**
-     * Connects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it only receives
-     * datagrams from, and sends datagrams to, the given remote <i>peer</i>
-     * address.  Once connected, datagrams may not be received from or sent to
-     * any other address.  A datagram socket remains connected until it is
-     * explicitly disconnected or until it is closed.
-     *
-     * <p> This method performs exactly the same security checks as the {@link
-     * java.net.DatagramSocket#connect connect} method of the {@link
-     * java.net.DatagramSocket} class.  That is, if a security manager has been
-     * installed then this method verifies that its {@link
-     * java.lang.SecurityManager#checkAccept checkAccept} and {@link
-     * java.lang.SecurityManager#checkConnect checkConnect} methods permit
-     * datagrams to be received from and sent to, respectively, the given
-     * remote address.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @param  remote
-     *         The remote address to which this channel is to be connected
-     *
-     * @return  This datagram channel
-     *
-     * @throws  ClosedChannelException
-     *          If this channel is closed
-     *
-     * @throws  SecurityException
-     *          If a security manager has been installed
-     *          and it does not permit access to the given remote address
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel connect(SocketAddress remote)
-        throws IOException;
-
-    /**
-     * Disconnects this channel's socket.
-     *
-     * <p> The channel's socket is configured so that it can receive datagrams
-     * from, and sends datagrams to, any remote address so long as the security
-     * manager, if installed, permits it.
-     *
-     * <p> This method may be invoked at any time. Whether it has any effect
-     * on outstanding read or write operations is implementation specific and
-     * therefore not specified.
-     *
-     * @return  This datagram channel
-     *
-     * @throws  IOException
-     *          If some other I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel disconnect() throws IOException;
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> The datagram is transferred into the given byte buffer starting at
-     * its current position, as if by a regular {@link AsynchronousByteChannel#read
-     * read} operation. If there are fewer bytes remaining in the buffer
-     * than are required to hold the datagram then the remainder of the datagram
-     * is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * <p> When a security manager has been installed and the channel is not
-     * connected, then it verifies that the source's address and port number are
-     * permitted by the security manager's {@link SecurityManager#checkAccept
-     * checkAccept} method. The permission check is performed with privileges that
-     * are restricted by the calling context of this method. If the permission
-     * check fails then the operation completes with a {@link SecurityException}.
-     * The overhead of this security check can be avoided by first connecting the
-     * socket via the {@link #connect connect} method.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void receive(ByteBuffer dst,
-                                     long timeout,
-                                     TimeUnit unit,
-                                     A attachment,
-                                     CompletionHandler<SocketAddress,? super A> handler);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is the datagram's source address.
-     *
-     * <p> This method is equivalent to invoking {@link
-     * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
-     * timeout of {@code 0L}.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public final <A> void receive(ByteBuffer dst,
-                                  A attachment,
-                                  CompletionHandler<SocketAddress,? super A> handler)
-    {
-        receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The method behaves in exactly the same manner as the {@link
-     * #receive(ByteBuffer,Object,CompletionHandler)
-     * receive(ByteBuffer,Object,CompletionHandler)} method except that instead
-     * of specifying a completion handler, this method returns a {@code Future}
-     * representing the pending result. The {@code Future}'s {@link Future#get()
-     * get} method returns the datagram's source address.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  IllegalArgumentException
-     *          If the buffer is read-only
-     */
-    public abstract Future<SocketAddress> receive(ByteBuffer dst);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The {@code handler} parameter is a completion handler
-     * that is invoked when the send completes (or fails). The result passed to
-     * the completion handler is the number of bytes sent.
-     *
-     * <p> Otherwise this method works in the same manner as the {@link
-     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
-     * method.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void send(ByteBuffer src,
-                                  SocketAddress target,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * Sends a datagram via this channel.
-     *
-     * <p> This method initiates sending of a datagram from the given buffer to
-     * the given address. The method behaves in exactly the same manner as the
-     * {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
-     * send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
-     * that instead of specifying a completion handler, this method returns a
-     * {@code Future} representing the pending result. The {@code Future}'s
-     * {@link Future#get() get} method returns the number of bytes sent.
-     *
-     * @param   src
-     *          The buffer containing the datagram to be sent
-     * @param   target
-     *          The address to which the datagram is to be sent
-     *
-     * @return  a {@code Future} object representing the pending result
-     *
-     * @throws  UnresolvedAddressException
-     *          If the given remote address is not fully resolved
-     * @throws  UnsupportedAddressTypeException
-     *          If the type of the given remote address is not supported
-     * @throws  IllegalArgumentException
-     *          If the channel's socket is connected and is connected to an
-     *          address that is not equal to {@code target}
-     * @throws  SecurityException
-     *          If a security manager has been installed and it does not permit
-     *          datagrams to be sent to the given address
-     */
-    public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
-
-    /**
-     * Receives a datagram via this channel.
-     *
-     * <p> This method initiates the receiving of a datagram into the given
-     * buffer. The {@code handler} parameter is a completion handler that is
-     * invoked when the receive operation completes (or fails). The result
-     * passed to the completion handler is number of bytes read.
-     *
-     * <p> This method may only be invoked if this channel is connected, and it
-     * only accepts datagrams from the peer that the channel is connected too.
-     * The datagram is transferred into the given byte buffer starting at
-     * its current position and exactly as specified in the {@link
-     * AsynchronousByteChannel} interface. If there are fewer bytes
-     * remaining in the buffer than are required to hold the datagram then the
-     * remainder of the datagram is silently discarded.
-     *
-     * <p> If a timeout is specified and the timeout elapses before the operation
-     * completes then the operation completes with the exception {@link
-     * InterruptedByTimeoutException}. When a timeout elapses then the state of
-     * the {@link ByteBuffer} is not defined. The buffers should be discarded or
-     * at least care must be taken to ensure that the buffer is not accessed
-     * while the channel remains open.
-     *
-     * @param   dst
-     *          The buffer into which the datagram is to be transferred
-     * @param   timeout
-     *          The timeout, or {@code 0L} for no timeout
-     * @param   unit
-     *          The time unit of the {@code timeout} argument
-     * @param   attachment
-     *          The object to attach to the I/O operation; can be {@code null}
-     * @param   handler
-     *          The handler for consuming the result
-     *
-     * @throws  IllegalArgumentException
-     *          If the timeout is negative or buffer is read-only
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    public abstract <A> void read(ByteBuffer dst,
-                                  long timeout,
-                                  TimeUnit unit,
-                                  A attachment,
-                                  CompletionHandler<Integer,? super A> handler);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public final <A> void read(ByteBuffer dst,
-                               A attachment,
-                               CompletionHandler<Integer,? super A> handler)
-    {
-        read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
-    }
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> read(ByteBuffer dst);
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract <A> void  write(ByteBuffer src,
-                                    A attachment,
-                                    CompletionHandler<Integer,? super A> handler);
-
-
-    /**
-     * @throws  NotYetConnectedException
-     *          If this channel is not connected
-     * @throws  ShutdownChannelGroupException
-     *          If the channel group has terminated
-     */
-    @Override
-    public abstract Future<Integer> write(ByteBuffer src);
-}
--- a/src/share/classes/java/nio/channels/package-info.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/nio/channels/package-info.java	Thu Nov 18 10:35:46 2010 -0800
@@ -232,8 +232,6 @@
  *     <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
  *     <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
- * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousDatagramChannel}</tt></td>
- *     <td>An asynchronous channel to a datagram-oriented socket</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td>
  *     <td>A handler for consuming the result of an asynchronous operation</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td>
--- a/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java	Thu Nov 18 10:35:46 2010 -0800
@@ -26,7 +26,6 @@
 package java.nio.channels.spi;
 
 import java.nio.channels.*;
-import java.net.ProtocolFamily;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.ServiceLoader;
@@ -239,26 +238,4 @@
      */
     public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
         (AsynchronousChannelGroup group) throws IOException;
-
-    /**
-     * Opens an asynchronous datagram channel.
-     *
-     * @param   family
-     *          The protocol family, or {@code null} for the default protocol
-     *          family
-     * @param   group
-     *          The group to which the channel is bound, or {@code null} to
-     *          bind to the default group
-     *
-     * @return  The new channel
-     *
-     * @throws  IllegalChannelGroupException
-     *          If the provider that created the group differs from this provider
-     * @throws  ShutdownChannelGroupException
-     *          The group is shutdown
-     * @throws  IOException
-     *          If an I/O error occurs
-     */
-    public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
-        (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/security/AlgorithmConstraints.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.Set;
+
+/**
+ * This interface specifies constraints for cryptographic algorithms,
+ * keys (key sizes), and other algorithm parameters.
+ * <p>
+ * {@code AlgorithmConstraints} objects are immutable.  An implementation
+ * of this interface should not provide methods that can change the state
+ * of an instance once it has been created.
+ * <p>
+ * Note that {@code AlgorithmConstraints} can be used to represent the
+ * restrictions described by the security properties
+ * {@code jdk.certpath.disabledAlgorithms} and
+ * {@code jdk.tls.disabledAlgorithms}, or could be used by a
+ * concrete {@code PKIXCertPathChecker} to check whether a specified
+ * certificate in the certification path contains the required algorithm
+ * constraints.
+ *
+ * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
+ * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+ *
+ * @since 1.7
+ */
+
+public interface AlgorithmConstraints {
+
+    /**
+     * Determines whether an algorithm is granted permission for the
+     * specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the algorithm is permitted and can be used for all
+     *     of the specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+            String algorithm, AlgorithmParameters parameters);
+
+    /**
+     * Determines whether a key is granted permission for the specified
+     * cryptographic primitives.
+     * <p>
+     * This method is usually used to check key size and key usage.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param key the key
+     *
+     * @return true if the key can be used for all of the specified
+     *     cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives is null or empty,
+     *     or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives, Key key);
+
+    /**
+     * Determines whether an algorithm and the corresponding key are granted
+     * permission for the specified cryptographic primitives.
+     *
+     * @param primitives a set of cryptographic primitives
+     * @param algorithm the algorithm name
+     * @param key the key
+     * @param parameters the algorithm parameters, or null if no additional
+     *     parameters
+     *
+     * @return true if the key and the algorithm can be used for all of the
+     *     specified cryptographic primitives
+     *
+     * @throws IllegalArgumentException if primitives or algorithm is null
+     *     or empty, or the key is null
+     */
+    public boolean permits(Set<CryptoPrimitive> primitives,
+                String algorithm, Key key, AlgorithmParameters parameters);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/security/CryptoPrimitive.java	Thu Nov 18 10:35:46 2010 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * An enumeration of cryptographic primitives.
+ *
+ * @since 1.7
+ */
+public enum CryptoPrimitive {
+    /**
+     * Hash function
+     */
+    MESSAGE_DIGEST,
+
+    /**
+     * Cryptographic random number generator
+     */
+    SECURE_RANDOM,
+
+    /**
+     * Symmetric primitive: block cipher
+     */
+    BLOCK_CIPHER,
+
+    /**
+     * Symmetric primitive: stream cipher
+     */
+    STREAM_CIPHER,
+
+    /**
+     * Symmetric primitive: message authentication code
+     */
+    MAC,
+
+    /**
+     * Symmetric primitive: key wrap
+     */
+    KEY_WRAP,
+
+    /**
+     * Asymmetric primitive: public key encryption
+     */
+    PUBLIC_KEY_ENCRYPTION,
+
+    /**
+     * Asymmetric primitive: signature scheme
+     */
+    SIGNATURE,
+
+    /**
+     * Asymmetric primitive: key encapsulation mechanism
+     */
+    KEY_ENCAPSULATION,
+
+    /**
+     * Asymmetric primitive: key agreement and key distribution
+     */
+    KEY_AGREEMENT
+}
--- a/src/share/classes/java/security/cert/CertificateRevokedException.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/security/cert/CertificateRevokedException.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, 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
@@ -61,8 +61,8 @@
      */
     private final CRLReason reason;
     /**
-     * @serial the name of the authority that signed the certificate's
-     *    revocation status information
+     * @serial the <code>X500Principal</code> that represents the name of the
+     * authority that signed the certificate's revocation status information
      */
     private final X500Principal authority;
 
@@ -79,8 +79,9 @@
      * @param extensions a map of X.509 Extensions. Each key is an OID String
      *    that maps to the corresponding Extension. The map is copied to
      *    prevent subsequent modification.
-     * @param authority the name of the authority that signed the certificate's
-     *    revocation status information
+     * @param authority the <code>X500Principal</code> that represents the name
+     *    of the authority that signed the certificate's revocation status
+     *    information
      * @throws NullPointerException if <code>revocationDate</code>,
      *    <code>reason</code>, <code>authority</code>, or
      *    <code>extensions</code> is <code>null</code>
@@ -121,8 +122,8 @@
      * Returns the name of the authority that signed the certificate's
      * revocation status information.
      *
-     * @return the name of the authority that signed the certificate's
-     *    revocation status information
+     * @return the <code>X500Principal</code> that represents the name of the
+     *     authority that signed the certificate's revocation status information
      */
     public X500Principal getAuthorityName() {
         return authority;
--- a/src/share/classes/java/text/DateFormatSymbols.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/text/DateFormatSymbols.java	Thu Nov 18 10:35:46 2010 -0800
@@ -44,11 +44,12 @@
 import java.lang.ref.SoftReference;
 import java.text.spi.DateFormatSymbolsProvider;
 import java.util.Arrays;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.spi.LocaleServiceProvider;
 import sun.util.LocaleServiceProviderPool;
 import sun.util.TimeZoneNameUtility;
@@ -321,20 +322,64 @@
      * @since 1.6
      */
     public static final DateFormatSymbols getInstance(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return (DateFormatSymbols) getCachedInstance(locale).clone();
+    }
+
+    /**
+     * Returns a DateFormatSymbols provided by a provider or found in
+     * the cache. Note that this method returns a cached instance,
+     * not its clone. Therefore, the instance should never be given to
+     * an application.
+     */
+    static final DateFormatSymbols getInstanceRef(Locale locale) {
+        DateFormatSymbols dfs = getProviderInstance(locale);
+        if (dfs != null) {
+            return dfs;
+        }
+        return getCachedInstance(locale);
+    }
+
+    private static DateFormatSymbols getProviderInstance(Locale locale) {
+        DateFormatSymbols providersInstance = null;
 
         // Check whether a provider can provide an implementation that's closer
         // to the requested locale than what the Java runtime itself can provide.
         LocaleServiceProviderPool pool =
             LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
         if (pool.hasProviders()) {
-            DateFormatSymbols providersInstance = pool.getLocalizedObject(
-                                DateFormatSymbolsGetter.INSTANCE, locale);
-            if (providersInstance != null) {
-                return providersInstance;
+            providersInstance = pool.getLocalizedObject(
+                                    DateFormatSymbolsGetter.INSTANCE, locale);
+        }
+        return providersInstance;
+    }
+
+    /**
+     * Returns a cached DateFormatSymbols if it's found in the
+     * cache. Otherwise, this method returns a newly cached instance
+     * for the given locale.
+     */
+    private static DateFormatSymbols getCachedInstance(Locale locale) {
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs = null;
+        if (ref == null || (dfs = ref.get()) == null) {
+            dfs = new DateFormatSymbols(locale);
+            ref = new SoftReference<DateFormatSymbols>(dfs);
+            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
+            if (x != null) {
+                DateFormatSymbols y = x.get();
+                if (y != null) {
+                    dfs = y;
+                } else {
+                    // Replace the empty SoftReference with ref.
+                    cachedInstances.put(locale, ref);
+                }
             }
         }
-
-        return new DateFormatSymbols(locale);
+        return dfs;
     }
 
     /**
@@ -597,56 +642,44 @@
     static final int millisPerHour = 60*60*1000;
 
     /**
-     * Cache to hold the FormatData and TimeZoneNames ResourceBundles
-     * of a Locale.
+     * Cache to hold DateFormatSymbols instances per Locale.
      */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
-
-    /**
-     * Look up resource data for the desiredLocale in the cache; update the
-     * cache if necessary.
-     */
-    private static ResourceBundle cacheLookup(Locale desiredLocale) {
-        ResourceBundle rb;
-        SoftReference data
-            = (SoftReference)cachedLocaleData.get(desiredLocale);
-        if (data == null) {
-            rb = LocaleData.getDateFormatData(desiredLocale);
-            data = new SoftReference(rb);
-            cachedLocaleData.put(desiredLocale, data);
-        } else {
-            if ((rb = (ResourceBundle)data.get()) == null) {
-                rb = LocaleData.getDateFormatData(desiredLocale);
-                data = new SoftReference(rb);
-            }
-        }
-        return rb;
-    }
+    private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
+        = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
 
     private void initializeData(Locale desiredLocale) {
-        int i;
-        ResourceBundle resource = cacheLookup(desiredLocale);
+        locale = desiredLocale;
 
-        // FIXME: cache only ResourceBundle. Hence every time, will do
-        // getObject(). This won't be necessary if the Resource itself
-        // is cached.
-        eras = (String[])resource.getObject("Eras");
+        // Copy values of a cached instance if any.
+        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
+        DateFormatSymbols dfs;
+        if (ref != null && (dfs = ref.get()) != null) {
+            copyMembers(dfs, this);
+            return;
+        }
+
+        // Initialize the fields from the ResourceBundle for locale.
+        ResourceBundle resource = LocaleData.getDateFormatData(locale);
+
+        eras = resource.getStringArray("Eras");
         months = resource.getStringArray("MonthNames");
         shortMonths = resource.getStringArray("MonthAbbreviations");
-        String[] lWeekdays = resource.getStringArray("DayNames");
-        weekdays = new String[8];
-        weekdays[0] = "";  // 1-based
-        for (i=0; i<lWeekdays.length; i++)
-            weekdays[i+1] = lWeekdays[i];
-        String[] sWeekdays = resource.getStringArray("DayAbbreviations");
-        shortWeekdays = new String[8];
-        shortWeekdays[0] = "";  // 1-based
-        for (i=0; i<sWeekdays.length; i++)
-            shortWeekdays[i+1] = sWeekdays[i];
         ampms = resource.getStringArray("AmPmMarkers");
         localPatternChars = resource.getString("DateTimePatternChars");
 
-        locale = desiredLocale;
+        // Day of week names are stored in a 1-based array.
+        weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
+        shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
+    }
+
+    private static String[] toOneBasedArray(String[] src) {
+        int len = src.length;
+        String[] dst = new String[len + 1];
+        dst[0] = "";
+        for (int i = 0; i < len; i++) {
+            dst[i + 1] = src[i];
+        }
+        return dst;
     }
 
     /**
--- a/src/share/classes/java/text/DecimalFormat.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/text/DecimalFormat.java	Thu Nov 18 10:35:46 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,9 +46,10 @@
 import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Currency;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import sun.util.resources.LocaleData;
@@ -394,14 +395,14 @@
     public DecimalFormat() {
         Locale def = Locale.getDefault(Locale.Category.FORMAT);
         // try to get the pattern from the cache
-        String pattern = (String) cachedLocaleData.get(def);
+        String pattern = cachedLocaleData.get(def);
         if (pattern == null) {  /* cache miss */
             // Get the pattern for the default locale.
             ResourceBundle rb = LocaleData.getNumberFormatData(def);
             String[] all = rb.getStringArray("NumberPatterns");
             pattern = all[0];
             /* update cache */
-            cachedLocaleData.put(def, pattern);
+            cachedLocaleData.putIfAbsent(def, pattern);
         }
 
         // Always applyPattern after the symbols are set
@@ -3272,5 +3273,6 @@
     /**
      * Cache to hold the NumberPattern of a Locale.
      */
-    private static Hashtable cachedLocaleData = new Hashtable(3);
+    private static final ConcurrentMap<Locale, String> cachedLocaleData
+        = new ConcurrentHashMap<Locale, String>(3);
 }
--- a/src/share/classes/java/text/RuleBasedCollator.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/text/RuleBasedCollator.java	Thu Nov 18 10:35:46 2010 -0800
@@ -335,9 +335,15 @@
      * collation rules.  Returns information about whether a string is less
      * than, greater than or equal to another string in a language.
      * This can be overriden in a subclass.
+     *
+     * @exception NullPointerException if <code>source</code> or <code>target</code> is null.
      */
     public synchronized int compare(String source, String target)
     {
+        if (source == null || target == null) {
+            throw new NullPointerException();
+        }
+
         // The basic algorithm here is that we use CollationElementIterators
         // to step through both the source and target strings.  We compare each
         // collation element in the source string against the corresponding one
--- a/src/share/classes/java/text/SimpleDateFormat.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/text/SimpleDateFormat.java	Thu Nov 18 10:35:46 2010 -0800
@@ -44,13 +44,14 @@
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.calendar.CalendarUtils;
 import sun.util.calendar.ZoneInfoFile;
 import sun.util.resources.LocaleData;
@@ -503,14 +504,14 @@
     /**
      * Cache to hold the DateTimePatterns of a Locale.
      */
-    private static Hashtable<String,String[]> cachedLocaleData
-        = new Hashtable<String,String[]>(3);
+    private static final ConcurrentMap<String, String[]> cachedLocaleData
+        = new ConcurrentHashMap<String, String[]>(3);
 
     /**
      * Cache NumberFormat instances with Locale key.
      */
-    private static Hashtable<Locale,NumberFormat> cachedNumberFormatData
-        = new Hashtable<Locale,NumberFormat>(3);
+    private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
+        = new ConcurrentHashMap<Locale, NumberFormat>(3);
 
     /**
      * The Locale used to instantiate this
@@ -579,7 +580,7 @@
 
         initializeCalendar(locale);
         this.pattern = pattern;
-        this.formatData = DateFormatSymbols.getInstance(locale);
+        this.formatData = DateFormatSymbols.getInstanceRef(locale);
         this.locale = locale;
         initialize(locale);
     }
@@ -632,9 +633,9 @@
                 dateTimePatterns = r.getStringArray("DateTimePatterns");
             }
             /* update cache */
-            cachedLocaleData.put(key, dateTimePatterns);
+            cachedLocaleData.putIfAbsent(key, dateTimePatterns);
         }
-        formatData = DateFormatSymbols.getInstance(loc);
+        formatData = DateFormatSymbols.getInstanceRef(loc);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
             Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
                                      dateTimePatterns[dateStyle + 4]};
@@ -665,7 +666,7 @@
             numberFormat.setGroupingUsed(false);
 
             /* update cache */
-            cachedNumberFormatData.put(loc, numberFormat);
+            cachedNumberFormatData.putIfAbsent(loc, numberFormat);
         }
         numberFormat = (NumberFormat) numberFormat.clone();
 
@@ -897,7 +898,7 @@
      * so we can call it from readObject().
      */
     private void initializeDefaultCentury() {
-        calendar.setTime( new Date() );
+        calendar.setTimeInMillis(System.currentTimeMillis());
         calendar.add( Calendar.YEAR, -80 );
         parseAmbiguousDatesAsAfter(calendar.getTime());
     }
@@ -921,7 +922,7 @@
      * @since 1.2
      */
     public void set2DigitYearStart(Date startDate) {
-        parseAmbiguousDatesAsAfter(startDate);
+        parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
     }
 
     /**
@@ -934,7 +935,7 @@
      * @since 1.2
      */
     public Date get2DigitYearStart() {
-        return defaultCenturyStart;
+        return (Date) defaultCenturyStart.clone();
     }
 
     /**
--- a/src/share/classes/java/util/ArrayList.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/util/ArrayList.java	Thu Nov 18 10:35:46 2010 -0800
@@ -176,6 +176,11 @@
      * @param minCapacity the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
+        if (minCapacity > 0)
+            ensureCapacityInternal(minCapacity);
+    }
+
+    private void ensureCapacityInternal(int minCapacity) {
         modCount++;
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
@@ -403,7 +408,7 @@
      * @return <tt>true</tt> (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         elementData[size++] = e;
         return true;
     }
@@ -420,7 +425,7 @@
     public void add(int index, E element) {
         rangeCheckForAdd(index);
 
-        ensureCapacity(size + 1);  // Increments modCount!!
+        ensureCapacityInternal(size + 1);  // Increments modCount!!
         System.arraycopy(elementData, index, elementData, index + 1,
                          size - index);
         elementData[index] = element;
@@ -524,7 +529,7 @@
     public boolean addAll(Collection<? extends E> c) {
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
         System.arraycopy(a, 0, elementData, size, numNew);
         size += numNew;
         return numNew != 0;
@@ -550,7 +555,7 @@
 
         Object[] a = c.toArray();
         int numNew = a.length;
-        ensureCapacity(size + numNew);  // Increments modCount
+        ensureCapacityInternal(size + numNew);  // Increments modCount
 
         int numMoved = size - index;
         if (numMoved > 0)
--- a/src/share/classes/java/util/Arrays.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/util/Arrays.java	Thu Nov 18 10:35:46 2010 -0800
@@ -97,7 +97,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(int[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -136,7 +137,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(long[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -175,7 +177,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(short[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -214,7 +217,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(char[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -253,7 +257,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(byte[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -308,7 +313,8 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(float[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /**
@@ -363,12 +369,12 @@
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(double[] a, int fromIndex, int toIndex) {
-        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+        rangeCheck(a.length, fromIndex, toIndex);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
     }
 
     /*
      * Sorting of complex type arrays.
-     *
      */
 
     /**
--- a/src/share/classes/java/util/Calendar.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/util/Calendar.java	Thu Nov 18 10:35:46 2010 -0800
@@ -51,6 +51,8 @@
 import java.security.ProtectionDomain;
 import java.text.DateFormat;
 import java.text.DateFormatSymbols;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import sun.util.BuddhistCalendar;
 import sun.util.calendar.ZoneInfo;
 import sun.util.resources.LocaleData;
@@ -837,7 +839,8 @@
      * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
      * of a Locale.
      */
-    private static Hashtable<Locale, int[]> cachedLocaleData = new Hashtable<Locale, int[]>(3);
+    private static final ConcurrentMap<Locale, int[]> cachedLocaleData
+        = new ConcurrentHashMap<Locale, int[]>(3);
 
     // Special values of stamp[]
     /**
@@ -1022,7 +1025,7 @@
             // returns a BuddhistCalendar instance.
             if ("th".equals(aLocale.getLanguage())
                     && ("TH".equals(aLocale.getCountry()))) {
-                    cal = new BuddhistCalendar(zone, aLocale);
+                cal = new BuddhistCalendar(zone, aLocale);
             } else {
                 cal = new GregorianCalendar(zone, aLocale);
             }
@@ -2588,7 +2591,7 @@
             data = new int[2];
             data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
             data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
-            cachedLocaleData.put(desiredLocale, data);
+            cachedLocaleData.putIfAbsent(desiredLocale, data);
         }
         firstDayOfWeek = data[0];
         minimalDaysInFirstWeek = data[1];
--- a/src/share/classes/java/util/DualPivotQuicksort.java	Fri Oct 22 14:14:54 2010 -0400
+++ b/src/share/classes/java/util/DualPivotQuicksort.java	Thu Nov 18 10:35:46 2010 -0800
@@ -36,7 +36,7 @@
  * @author Jon Bentley
  * @author Josh Bloch
  *
- * @version 2010.06.21 m765.827.12i:5\7
+ * @version 2010.10.13 m765.827.12i:5\7p
  * @since 1.7
  */
 final class DualPivotQuicksort {
@@ -54,26 +54,26 @@
      * If the length of an array to be sorted is less than this
      * constant, insertion sort is used in preference to Quicksort.
      */
-    private static final int INSERTION_SORT_THRESHOLD = 32;
+    private static final int INSERTION_SORT_THRESHOLD = 47;
 
     /**
-     * If the length of a byte array to be sorted is greater than
-     * this constant, counting sort is used in preference to Quicksort.
+     * If the length of a byte array to be sorted is greater than this
+     * constant, counting sort is used in preference to insertion sort.
      */
-    private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 128;
+    private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 29;
 
     /**
      * If the length of a short or char array to be sorted is greater
      * than this constant, counting sort is used in preference to Quicksort.
      */
-    private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
+    private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 3200;
 
     /*
      * Sorting methods for seven primitive types.
      */
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
@@ -82,58 +82,34 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(int[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sort(a, fromIndex, toIndex - 1, true);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     */
+    public static void sort(int[] a, int left, int right) {
+        sort(a, left, right, true);
+    }
+
+    /**
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(int[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    int ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     int ai = a[i + 1];
@@ -145,12 +121,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    int a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                int last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -232,10 +250,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 int ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -244,13 +266,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -265,7 +291,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -299,7 +325,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     int ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -311,7 +337,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -337,7 +363,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -356,28 +382,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 int ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -397,14 +415,18 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
@@ -413,58 +435,34 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(long[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sort(a, fromIndex, toIndex - 1, true);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     */
+    public static void sort(long[] a, int left, int right) {
+        sort(a, left, right, true);
+    }
+
+    /**
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(long[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    long ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     long ai = a[i + 1];
@@ -476,12 +474,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    long a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                long last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -563,10 +603,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 long ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -575,13 +619,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -596,7 +644,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -630,7 +678,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     long ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -642,7 +690,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -668,7 +716,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -687,28 +735,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 long ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -728,45 +768,51 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(short[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
+    public static void sort(short[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            int[] count = new int[NUM_SHORT_VALUES];
 
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i] - Short.MIN_VALUE]++;
+            }
+            for (int i = NUM_SHORT_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                short value = (short) (i + Short.MIN_VALUE);
+                int s = count[i];
+
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
+            }
+        } else { // Use Dual-Pivot Quicksort on small arrays
+            sort(a, left, right, true);
         }
     }
 
@@ -774,66 +820,23 @@
     private static final int NUM_SHORT_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void countingSort(short[] a, int left, int right) {
-        int[] count = new int[NUM_SHORT_VALUES];
-
-        for (int i = left; i <= right; i++) {
-            count[a[i] - Short.MIN_VALUE]++;
-        }
-        for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) {
-            while (count[i] == 0) {
-                i--;
-            }
-            short value = (short) (i + Short.MIN_VALUE);
-            int s = count[i];
-
-            do {
-                a[k--] = value;
-            } while (--s > 0);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(short[] a, int left, int right,boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    short ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     short ai = a[i + 1];
@@ -845,12 +848,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    short a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                short last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -932,10 +977,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 short ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -944,13 +993,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -965,7 +1018,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -999,7 +1052,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     short ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -1011,7 +1064,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -1037,7 +1090,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -1056,28 +1109,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 short ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -1097,45 +1142,51 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(char[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
+    public static void sort(char[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            int[] count = new int[NUM_CHAR_VALUES];
 
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i]]++;
+            }
+            for (int i = NUM_CHAR_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                char value = (char) i;
+                int s = count[i];
+
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
+            }
+        } else { // Use Dual-Pivot Quicksort on small arrays
+            sort(a, left, right, true);
         }
     }
 
@@ -1143,66 +1194,23 @@
     private static final int NUM_CHAR_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void countingSort(char[] a, int left, int right) {
-        int[] count = new int[NUM_CHAR_VALUES];
-
-        for (int i = left; i <= right; i++) {
-            count[a[i]]++;
-        }
-        for (int i = 0, k = left; k <= right; i++) {
-            while (count[i] == 0) {
-                i++;
-            }
-            char value = (char) i;
-            int s = count[i];
-
-            do {
-                a[k++] = value;
-            } while (--s > 0);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(char[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    char ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     char ai = a[i + 1];
@@ -1214,12 +1222,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    char a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                char last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -1301,10 +1351,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 char ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -1313,13 +1367,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -1334,7 +1392,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -1368,7 +1426,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     char ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -1380,7 +1438,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -1406,7 +1464,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -1425,28 +1483,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 char ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -1466,442 +1516,90 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(byte[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(byte[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
-        }
-    }
-
     /** The number of distinct byte values. */
     private static final int NUM_BYTE_VALUES = 1 << 8;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified array.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(byte[] a) {
+        sort(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void countingSort(byte[] a, int left, int right) {
-        int[] count = new int[NUM_BYTE_VALUES];
+    public static void sort(byte[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+            int[] count = new int[NUM_BYTE_VALUES];
 
-        for (int i = left; i <= right; i++) {
-            count[a[i] - Byte.MIN_VALUE]++;
-        }
-        for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) {
-            while (count[i] == 0) {
-                i--;
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i] - Byte.MIN_VALUE]++;
             }
-            byte value = (byte) (i + Byte.MIN_VALUE);
-            int s = count[i];
+            for (int i = NUM_BYTE_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                byte value = (byte) (i + Byte.MIN_VALUE);
+                int s = count[i];
 
-            do {
-                a[k--] = value;
-            } while (--s > 0);
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
+            }
+        } else { // Use insertion sort on small arrays
+            for (int i = left, j = i; i < right; j = ++i) {
+                byte ai = a[i + 1];
+                while (ai < a[j]) {
+                    a[j + 1] = a[j];
+                    if (j-- == left) {
+                        break;
+                    }
+                }
+                a[j + 1] = ai;
+            }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
-     */
-    private static void sort(byte[] a, int left, int right, boolean leftmost) {
-        int length = right - left + 1;
-
-        // Use insertion sort on tiny arrays
-        if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
-                /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    byte ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
-                 */
-                for (int i = left, j = i; i < right; j = ++i) {
-                    byte ai = a[i + 1];
-                    while (ai < a[j]) {
-                        a[j + 1] = a[j];
-                        if (j-- == left) {
-                            break;
-                        }
-                    }
-                    a[j + 1] = ai;
-                }
-            }
-            return;
-        }
-
-        // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
-
-        /*
-         * Sort five evenly spaced elements around (and including) the
-         * center element in the range. These elements will be used for
-         * pivot selection as described below. The choice for spacing
-         * these elements was empirically determined to work well on
-         * a wide variety of inputs.
-         */
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e2 = e3 - seventh;
-        int e1 = e2 - seventh;
-        int e4 = e3 + seventh;
-        int e5 = e4 + seventh;
-
-        // Sort these elements using insertion sort
-        if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
-
-        if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t;
-            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-        }
-        if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t;
-            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
-                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-            }
-        }
-        if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t;
-            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
-                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
-                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-                }
-            }
-        }
-
-        /*
-         * Use the second and fourth of the five sorted elements as pivots.
-         * These values are inexpensive approximations of the first and
-         * second terciles of the array. Note that pivot1 <= pivot2.
-         */
-        byte pivot1 = a[e2];
-        byte pivot2 = a[e4];
-
-        // Pointers
-        int less  = left;  // The index of the first element of center part
-        int great = right; // The index before the first element of right part
-
-        if (pivot1 != pivot2) {
-            /*
-             * The first and the last elements to be sorted are moved to the
-             * locations formerly occupied by the pivots. When partitioning
-             * is complete, the pivots are swapped back into their final
-             * positions, and excluded from subsequent sorting.
-             */
-            a[e2] = a[left];
-            a[e4] = a[right];
-
-            /*
-             * Skip elements, which are less or greater than pivot values.
-             */
-            while (a[++less] < pivot1);
-            while (a[--great] > pivot2);
-
-            /*
-             * Partitioning:
-             *
-             *   left part           center part                   right part
-             * +--------------------------------------------------------------+
-             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
-             * +--------------------------------------------------------------+
-             *               ^                          ^       ^
-             *               |                          |       |
-             *              less                        k     great
-             *
-             * Invariants:
-             *
-             *              all in (left, less)   < pivot1
-             *    pivot1 <= all in [less, k)     <= pivot2
-             *              all in (great, right) > pivot2
-             *
-             * Pointer k is the first index of ?-part.
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-                if (ak < pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less] = ak;
-                    less++;
-                } else if (ak > pivot2) { // Move a[k] to right part
-                    while (a[great] > pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] < pivot1) {
-                        a[k] = a[less];
-                        a[less] = a[great];
-                        less++;
-                    } else { // pivot1 <= a[great] <= pivot2
-                        a[k] = a[great];
-                    }
-                    a[great] = ak;
-                    great--;
-                }
-            }
-
-            // Swap pivots into their final positions
-            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-            a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-            // Sort left and right parts recursively, excluding known pivots
-            sort(a, left, less - 2, leftmost);
-            sort(a, great + 2, right, false);
-
-            /*
-             * If center part is too large (comprises > 5/7 of the array),
-             * swap internal pivot values to ends.
-             */
-            if (less < e1 && e5 < great) {
-                /*
-                 * Skip elements, which are equal to pivot values.
-                 */
-                while (a[less] == pivot1) {
-                    less++;
-                }
-                while (a[great] == pivot2) {
-                    great--;
-                }
-
-                /*
-                 * Partitioning:
-                 *
-                 *   left part         center part                  rig