changeset 13487:2d65c7859d7e

Merge
author twisti
date Tue, 22 Dec 2015 13:41:12 -0800
parents abcef5a34091 fb2a4d3c555b
children cb31a76eecd1
files src/java.base/share/classes/java/lang/ref/Reference.java src/java.base/share/classes/sun/misc/BASE64Decoder.java src/java.base/share/classes/sun/misc/BASE64Encoder.java src/java.base/share/classes/sun/misc/CharacterDecoder.java src/java.base/share/classes/sun/misc/CharacterEncoder.java src/java.base/share/classes/sun/misc/HexDumpEncoder.java src/java.base/share/classes/sun/misc/ProxyGenerator.java src/java.base/share/classes/sun/misc/Queue.java src/java.base/share/classes/sun/misc/Request.java src/java.base/share/classes/sun/misc/RequestProcessor.java src/java.base/share/classes/sun/misc/UCDecoder.java src/java.base/share/classes/sun/misc/UCEncoder.java src/java.base/share/classes/sun/misc/UUDecoder.java src/java.base/share/classes/sun/misc/UUEncoder.java src/java.base/share/native/libzip/ZipFile.c test/sun/misc/Encode/DecodeBuffer.java test/sun/misc/Encode/Encode.java test/sun/misc/Encode/GetBytes.java
diffstat 168 files changed, 4977 insertions(+), 5418 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Dec 18 10:00:55 2015 -0800
+++ b/.hgtags	Tue Dec 22 13:41:12 2015 -0800
@@ -339,3 +339,4 @@
 559b626b01179420a94feb9c3d0f246970d2e3fa jdk9-b94
 8581faf0d474472e32f589bbc16db7eec912d83f jdk-9+95
 c021b855f51e572e63982654b17742cb1f814fb4 jdk-9+96
+fdd84b2265ddce7f50e084b7c8635189bba6f012 jdk-9+97
--- a/make/CompileDemos.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/CompileDemos.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -309,7 +309,7 @@
 
   ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX)
     # For C++, we also need some special treatment.
-    $1_LDFLAGS := $(LDFLAGS_CXX_JDK)
+    $1_LDFLAGS := $$(LDFLAGS_CXX_JDK)
     $1_LIBS := $(LIBCXX)
 
     ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
@@ -324,9 +324,9 @@
       OPTIMIZATION := LOW, \
       CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \
       CXXFLAGS := $$($1_CXXFLAGS), \
-      LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)) \
+      LDFLAGS := $(filter-out -incremental:no -opt:ref, $$(LDFLAGS_JDKLIB)) \
           $$($1_LDFLAGS), \
-      LDFLAGS_macosx := $(call SET_EXECUTABLE_ORIGIN), \
+      LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN), \
       LIBS := $$($1_LIBS), \
       LIBS_solaris := -lc, \
       VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/make/launcher/Launcher-java.base.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/launcher/Launcher-java.base.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -127,8 +127,7 @@
           $(BUILD_JEXEC_INC), \
       CFLAGS_linux := -fPIC, \
       CFLAGS_solaris := -KPIC, \
-      LDFLAGS := $(LDFLAGS_JDKEXE) \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
+      LDFLAGS := $(LDFLAGS_JDKEXE), \
       OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jexec_obj, \
       OUTPUT_DIR := $(BUILD_JEXEC_DST_DIR), \
       DEBUG_SYMBOLS := true, \
--- a/make/launcher/Launcher-jdk.pack200.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/launcher/Launcher-jdk.pack200.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -89,7 +89,6 @@
     MAPFILE := $(UNPACK_MAPFILE),\
     LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
         $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX)) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
     LIBS_solaris :=  -lc, \
--- a/make/launcher/LauncherCommon.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/launcher/LauncherCommon.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -25,6 +25,12 @@
 
 include NativeCompilation.gmk
 
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk binaries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  ENABLE_DEBUG_SYMBOLS := false
+endif
+
 # Prepare the find cache.
 $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src/java.base/share/native/launcher))
 
@@ -180,15 +186,12 @@
       CFLAGS_linux := -fPIC, \
       CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \
       CFLAGS_windows := $$($1_CFLAGS_windows), \
-      LDFLAGS := $(LDFLAGS_JDKEXE) \
+      LDFLAGS := $$(LDFLAGS_JDKEXE) \
           $$(ORIGIN_ARG) \
           $$($1_LDFLAGS), \
       LDFLAGS_linux := \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
           -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
-      LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \
       LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
-          $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
           -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
       MAPFILE := $$($1_MAPFILE), \
       LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
--- a/make/lib/Awt2dLibraries.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -683,7 +683,7 @@
     WARNINGS_AS_ERRORS_gcc := false, \
     WARNINGS_AS_ERRORS_solstudio := false, \
     MAPFILE := $(BUILD_LIBFONTMANAGER_MAPFILE), \
-    LDFLAGS := $(subst -Xlinker -z -Xlinker defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
+    LDFLAGS := $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
     LDFLAGS_macosx := -undefined dynamic_lookup, \
@@ -799,7 +799,7 @@
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
       LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
-      LDFLAGS_macosx := -Xlinker -rpath -Xlinker @loader_path, \
+      LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
       LIBS_unix := $(JAWT_LIBS) $(JDKLIB_LIBS), \
       LIBS_solaris := $(X_LIBS) -lXrender, \
       LIBS_macosx := -framework Cocoa, \
@@ -1034,7 +1034,7 @@
           -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop,  \
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN) \
-          -Xlinker -rpath -Xlinker @loader_path \
+          -Wl$(COMMA)-rpath$(COMMA)@loader_path \
           -L$(INSTALL_LIBRARIES_HERE), \
       LIBS := -lawt -losxapp -lawt_lwawt \
           -framework Cocoa \
--- a/make/lib/Lib-java.instrument.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/lib/Lib-java.instrument.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -65,7 +65,7 @@
         -L$(call FindLibDirForModule, java.base)/jli, \
     LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/jli) \
         -L$(call FindLibDirForModule, java.base)/jli, \
-    LDFLAGS_macosx := -Xlinker -all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
+    LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
     LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
     LDFLAGS_windows := -export:Agent_OnAttach, \
     LIBS := $(JDKLIB_LIBS), \
@@ -74,7 +74,8 @@
     LIBS_solaris := -ljli $(LIBDL), \
     LIBS_aix := -liconv -ljli_static $(LIBDL), \
     LIBS_macosx := -liconv -framework Cocoa -framework Security \
-        -framework ApplicationServices, \
+        -framework ApplicationServices \
+        $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
     LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \
         $(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib, \
     VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/make/lib/LibCommon.gmk	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/lib/LibCommon.gmk	Tue Dec 22 13:41:12 2015 -0800
@@ -46,6 +46,12 @@
   endif
 endif
 
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk libraries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  ENABLE_DEBUG_SYMBOLS := false
+endif
+
 ################################################################################
 # Find the default set of src dirs for a native library.
 # Param 1 - module name
--- a/make/mapfiles/libzip/mapfile-vers	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/mapfiles/libzip/mapfile-vers	Tue Dec 22 13:41:12 2015 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 SUNWprivate_1.1 {
 	global:
-		Java_java_util_jar_JarFile_getMetaInfEntryNames;
 		Java_java_util_zip_Adler32_update;
 		Java_java_util_zip_Adler32_updateBytes;
 		Java_java_util_zip_Adler32_updateByteBuffer;
@@ -48,25 +47,6 @@
 		Java_java_util_zip_Inflater_initIDs;
 		Java_java_util_zip_Inflater_reset;
 		Java_java_util_zip_Inflater_setDictionary;
-		Java_java_util_zip_ZipFile_close;
-		Java_java_util_zip_ZipFile_getCommentBytes;
-		Java_java_util_zip_ZipFile_freeEntry;
-		Java_java_util_zip_ZipFile_getEntry;
-		Java_java_util_zip_ZipFile_getEntryBytes;
-		Java_java_util_zip_ZipFile_getEntryCrc;
-		Java_java_util_zip_ZipFile_getEntryCSize;
-		Java_java_util_zip_ZipFile_getEntryFlag;
-		Java_java_util_zip_ZipFile_getEntryMethod;
-		Java_java_util_zip_ZipFile_getEntrySize;
-		Java_java_util_zip_ZipFile_getEntryTime;
-		Java_java_util_zip_ZipFile_getNextEntry;
-		Java_java_util_zip_ZipFile_getZipMessage;
-		Java_java_util_zip_ZipFile_getTotal;
-		Java_java_util_zip_ZipFile_initIDs;
-		Java_java_util_zip_ZipFile_open;
-		Java_java_util_zip_ZipFile_read;
-		Java_java_util_zip_ZipFile_startsWithLOC;
-
 		ZIP_Close;
 		ZIP_CRC32;
 		ZIP_FindEntry;
--- a/make/mapfiles/libzip/reorder-sparc	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/mapfiles/libzip/reorder-sparc	Tue Dec 22 13:41:12 2015 -0800
@@ -16,30 +16,14 @@
 text: .text%ZIP_Lock;
 text: .text%ZIP_Unlock;
 text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
 text: .text%Java_java_util_zip_Inflater_initIDs;
 text: .text%Java_java_util_zip_Inflater_init;
 text: .text%inflateInit2_;
 text: .text%zcalloc;
 text: .text%Java_java_util_zip_Inflater_inflateBytes;
-text: .text%Java_java_util_zip_ZipFile_read;
 text: .text%ZIP_Read;
 text: .text%zcfree;
-text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
 text: .text%Java_java_util_zip_Inflater_reset;
 text: .text%Java_java_util_zip_Inflater_end;
 text: .text%inflateEnd;
-text: .text%Java_java_util_zip_ZipFile_close;
 text: .text%ZIP_Close;
--- a/make/mapfiles/libzip/reorder-sparcv9	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/mapfiles/libzip/reorder-sparcv9	Tue Dec 22 13:41:12 2015 -0800
@@ -15,19 +15,6 @@
 text: .text%ZIP_Lock;
 text: .text%ZIP_Unlock;
 text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
 text: .text%Java_java_util_zip_Inflater_initIDs;
 text: .text%Java_java_util_zip_Inflater_init;
 text: .text%inflateInit2_;
@@ -35,7 +22,6 @@
 text: .text%inflateReset;
 text: .text%Java_java_util_zip_Inflater_inflateBytes;
 text: .text%inflate;
-text: .text%Java_java_util_zip_ZipFile_read;
 text: .text%ZIP_Read;
 text: .text%zcfree;
 text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
@@ -43,6 +29,5 @@
 text: .text%InflateFully;
 text: .text%inflateEnd;
 text: .text%Java_java_util_zip_Inflater_reset;
-text: .text%Java_java_util_zip_ZipFile_close;
 text: .text%ZIP_Close;
 text: .text%Java_java_util_zip_Inflater_end;
--- a/make/mapfiles/libzip/reorder-x86	Fri Dec 18 10:00:55 2015 -0800
+++ b/make/mapfiles/libzip/reorder-x86	Tue Dec 22 13:41:12 2015 -0800
@@ -16,34 +16,16 @@
 text: .text%ZIP_Lock;
 text: .text%ZIP_Unlock;
 text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
-text: .text%Java_java_util_zip_Inflater_initIDs;
-text: .text%Java_java_util_zip_Inflater_init;
 text: .text%inflateInit2_;
 text: .text%zcalloc;
 text: .text%inflateReset;
 text: .text%Java_java_util_zip_Inflater_inflateBytes;
 text: .text%inflate;
-text: .text%Java_java_util_zip_ZipFile_read;
 text: .text%ZIP_Read;
 text: .text%zcfree;
-text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
 text: .text%ZIP_ReadEntry;
 text: .text%InflateFully;
 text: .text%inflateEnd;
 text: .text%Java_java_util_zip_Inflater_reset;
-text: .text%Java_java_util_zip_ZipFile_close;
 text: .text%ZIP_Close;
 text: .text%Java_java_util_zip_Inflater_end;
--- a/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java	Tue Dec 22 13:41:12 2015 -0800
@@ -27,7 +27,7 @@
 
 import java.io.*;
 import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.spec.IvParameterSpec;
--- a/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java	Tue Dec 22 13:41:12 2015 -0800
@@ -30,7 +30,7 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.spec.GCMParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.*;
 
 /**
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java	Tue Dec 22 13:41:12 2015 -0800
@@ -31,7 +31,7 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.spec.PBEParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.*;
 
 
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java	Tue Dec 22 13:41:12 2015 -0800
@@ -33,7 +33,7 @@
 import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.PBEParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.*;
 
 /**
--- a/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java	Tue Dec 22 13:41:12 2015 -0800
@@ -30,7 +30,7 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.spec.RC2ParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.*;
 
 /**
--- a/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java	Tue Dec 22 13:41:12 2015 -0800
@@ -118,7 +118,7 @@
     public void debug(byte[] bytes) {
         if (DEBUG) {
             try {
-                new sun.misc.HexDumpEncoder().encodeBuffer(bytes, System.out);
+                new sun.security.util.HexDumpEncoder().encodeBuffer(bytes, System.out);
             } catch (IOException ioe) {
                 // Impossible
             }
--- a/src/java.base/share/classes/java/io/CharArrayReader.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/io/CharArrayReader.java	Tue Dec 22 13:41:12 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,9 +225,12 @@
      * Closes the stream and releases any system resources associated with
      * it.  Once the stream has been closed, further read(), ready(),
      * mark(), reset(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        buf = null;
+        synchronized (lock) {
+            buf = null;
+        }
     }
 }
--- a/src/java.base/share/classes/java/io/PushbackReader.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/io/PushbackReader.java	Tue Dec 22 13:41:12 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -241,13 +241,16 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * unread(), ready(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      *
      * @exception  IOException  If an I/O error occurs
      */
     public void close() throws IOException {
-        super.close();
-        buf = null;
+        synchronized (lock) {
+            super.close();
+            buf = null;
+        }
     }
 
     /**
--- a/src/java.base/share/classes/java/io/StringReader.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/io/StringReader.java	Tue Dec 22 13:41:12 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,9 +194,12 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * ready(), mark(), or reset() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        str = null;
+        synchronized (lock) {
+            str = null;
+        }
     }
 }
--- a/src/java.base/share/classes/java/lang/InheritableThreadLocal.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/InheritableThreadLocal.java	Tue Dec 22 13:41:12 2015 -0800
@@ -40,6 +40,11 @@
  * maintained in the variable (e.g., User ID, Transaction ID) must be
  * automatically transmitted to any child threads that are created.
  *
+ * <p>Note: During the creation of a new {@link
+ * Thread#Thread(ThreadGroup,Runnable,String,long,boolean) thread}, it is
+ * possible to <i>opt out</i> of receiving initial values for inheritable
+ * thread-local variables.
+ *
  * @author  Josh Bloch and Doug Lea
  * @see     ThreadLocal
  * @since   1.2
--- a/src/java.base/share/classes/java/lang/StackWalker.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StackWalker.java	Tue Dec 22 13:41:12 2015 -0800
@@ -304,8 +304,8 @@
     }
 
     /**
-     * Returns a {@code StackWalker} instance with the given {@ocde options} specifying
-     * the stack frame information it can access. If the given {@ocde options}
+     * Returns a {@code StackWalker} instance with the given {@code options} specifying
+     * the stack frame information it can access. If the given {@code options}
      * is empty, this {@code StackWalker} is configured to skip all
      * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
      * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
--- a/src/java.base/share/classes/java/lang/StringUTF16.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Tue Dec 22 13:41:12 2015 -0800
@@ -120,7 +120,8 @@
     public static byte[] toBytes(char[] value, int off, int len) {
         byte[] val = newBytesFor(len);
         for (int i = 0; i < len; i++) {
-            putChar(val, i, value[off++]);
+            putChar(val, i, value[off]);
+            off++;
         }
         return val;
     }
@@ -145,11 +146,14 @@
     @HotSpotIntrinsicCandidate
     private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
         for (int i = 0; i < len; i++) {
-            int c = src[srcOff++];
-            if (c >>> 8 != 0) {
-                return 0;
+            char c = src[srcOff];
+            if (c > 0xFF) {
+                len = 0;
+                break;
             }
-            dst[dstOff++] = (byte)c;
+            dst[dstOff] = (byte)c;
+            srcOff++;
+            dstOff++;
         }
         return len;
     }
@@ -160,11 +164,14 @@
         // We need a range check here because 'getChar' has no checks
         checkBoundsOffCount(srcOff, len, src.length);
         for (int i = 0; i < len; i++) {
-            int c = getChar(src, srcOff++);
-            if (c >>> 8 != 0) {
-                return 0;
+            char c = getChar(src, srcOff);
+            if (c > 0xFF) {
+                len = 0;
+                break;
             }
-            dst[dstOff++] = (byte)c;
+            dst[dstOff] = (byte)c;
+            srcOff++;
+            dstOff++;
         }
         return len;
     }
@@ -581,7 +588,7 @@
             bits |= cp;
             putChar(result, i, cp);
         }
-        if (bits >>> 8 != 0) {
+        if (bits > 0xFF) {
             return new String(result, UTF16);
         } else {
             return newString(result, 0, len);
@@ -678,7 +685,7 @@
             bits |= cp;
             putChar(result, i, cp);
         }
-        if (bits >>> 8 != 0) {
+        if (bits > 0xFF) {
             return new String(result, UTF16);
         } else {
             return newString(result, 0, len);
--- a/src/java.base/share/classes/java/lang/Thread.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/Thread.java	Tue Dec 22 13:41:12 2015 -0800
@@ -344,11 +344,11 @@
 
     /**
      * Initializes a Thread with the current AccessControlContext.
-     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)
+     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
      */
     private void init(ThreadGroup g, Runnable target, String name,
                       long stackSize) {
-        init(g, target, name, stackSize, null);
+        init(g, target, name, stackSize, null, true);
     }
 
     /**
@@ -361,9 +361,12 @@
      *        zero to indicate that this parameter is to be ignored.
      * @param acc the AccessControlContext to inherit, or
      *            AccessController.getContext() if null
+     * @param inheritThreadLocals if {@code true}, inherit initial values for
+     *            inheritable thread-locals from the constructing thread
      */
     private void init(ThreadGroup g, Runnable target, String name,
-                      long stackSize, AccessControlContext acc) {
+                      long stackSize, AccessControlContext acc,
+                      boolean inheritThreadLocals) {
         if (name == null) {
             throw new NullPointerException("name cannot be null");
         }
@@ -414,7 +417,7 @@
                 acc != null ? acc : AccessController.getContext();
         this.target = target;
         setPriority(priority);
-        if (parent.inheritableThreadLocals != null)
+        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
             this.inheritableThreadLocals =
                 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
         /* Stash the specified stack size in case the VM cares */
@@ -468,7 +471,7 @@
      * This is not a public constructor.
      */
     Thread(Runnable target, AccessControlContext acc) {
-        init(null, target, "Thread-" + nextThreadNum(), 0, acc);
+        init(null, target, "Thread-" + nextThreadNum(), 0, acc, true);
     }
 
     /**
@@ -678,6 +681,62 @@
     }
 
     /**
+     * Allocates a new {@code Thread} object so that it has {@code target}
+     * as its run object, has the specified {@code name} as its name,
+     * belongs to the thread group referred to by {@code group}, has
+     * the specified {@code stackSize}, and inherits initial values for
+     * {@linkplain InheritableThreadLocal inheritable thread-local} variables
+     * if {@code inheritThreadLocals} is {@code true}.
+     *
+     * <p> This constructor is identical to {@link
+     * #Thread(ThreadGroup,Runnable,String,long)} with the added ability to
+     * suppress, or not, the inheriting of initial values for inheritable
+     * thread-local variables from the constructing thread. This allows for
+     * finer grain control over inheritable thread-locals. Care must be taken
+     * when passing a value of {@code false} for {@code inheritThreadLocals},
+     * as it may lead to unexpected behavior if the new thread executes code
+     * that expects a specific thread-local value to be inherited.
+     *
+     * <p> Specifying a value of {@code true} for the {@code inheritThreadLocals}
+     * parameter will cause this constructor to behave exactly like the
+     * {@code Thread(ThreadGroup, Runnable, String, long)} constructor.
+     *
+     * @param  group
+     *         the thread group. If {@code null} and there is a security
+     *         manager, the group is determined by {@linkplain
+     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+     *         If there is not a security manager or {@code
+     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
+     *         is set to the current thread's thread group.
+     *
+     * @param  target
+     *         the object whose {@code run} method is invoked when this thread
+     *         is started. If {@code null}, this thread's run method is invoked.
+     *
+     * @param  name
+     *         the name of the new thread
+     *
+     * @param  stackSize
+     *         the desired stack size for the new thread, or zero to indicate
+     *         that this parameter is to be ignored
+     *
+     * @param  inheritThreadLocals
+     *         if {@code true}, inherit initial values for inheritable
+     *         thread-locals from the constructing thread, otherwise no initial
+     *         values are inherited
+     *
+     * @throws  SecurityException
+     *          if the current thread cannot create a thread in the specified
+     *          thread group
+     *
+     * @since 9
+     */
+    public Thread(ThreadGroup group, Runnable target, String name,
+                  long stackSize, boolean inheritThreadLocals) {
+        init(group, target, name, stackSize, null, inheritThreadLocals);
+    }
+
+    /**
      * Causes this thread to begin execution; the Java Virtual Machine
      * calls the <code>run</code> method of this thread.
      * <p>
--- a/src/java.base/share/classes/java/lang/ref/Finalizer.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/Finalizer.java	Tue Dec 22 13:41:12 2015 -0800
@@ -29,7 +29,6 @@
 import java.security.AccessController;
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
 import sun.misc.VM;
 
 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
@@ -131,7 +130,7 @@
                     for (ThreadGroup tgn = tg;
                          tgn != null;
                          tg = tgn, tgn = tg.getParent());
-                    Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer");
+                    Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
                     sft.start();
                     try {
                         sft.join();
@@ -190,10 +189,10 @@
                 }}});
     }
 
-    private static class FinalizerThread extends ManagedLocalsThread {
+    private static class FinalizerThread extends Thread {
         private volatile boolean running;
         FinalizerThread(ThreadGroup g) {
-            super(g, "Finalizer");
+            super(g, null, "Finalizer", 0, false);
         }
         public void run() {
             // in case of recursive call to run()
--- a/src/java.base/share/classes/java/lang/ref/Reference.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java	Tue Dec 22 13:41:12 2015 -0800
@@ -30,7 +30,6 @@
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
 
 /**
  * Abstract base class for reference objects.  This class defines the
@@ -129,7 +128,7 @@
 
     /* High-priority thread to enqueue pending References
      */
-    private static class ReferenceHandler extends ManagedLocalsThread {
+    private static class ReferenceHandler extends Thread {
 
         private static void ensureClassInitialized(Class<?> clazz) {
             try {
@@ -148,7 +147,7 @@
         }
 
         ReferenceHandler(ThreadGroup g, String name) {
-            super(g, name);
+            super(g, null, name, 0, false);
         }
 
         public void run() {
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java	Tue Dec 22 13:41:12 2015 -0800
@@ -42,4 +42,19 @@
      * @see GenericArrayType#getGenericComponentType()
      */
     AnnotatedType  getAnnotatedGenericComponentType();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedArrayType}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java	Tue Dec 22 13:41:12 2015 -0800
@@ -41,4 +41,26 @@
      * @see ParameterizedType#getActualTypeArguments()
      */
     AnnotatedType[] getAnnotatedActualTypeArguments();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+     *     top-level type, or a local or anonymous class, or a primitive type, or
+     *     void.
+     *
+     * @return an {@code AnnotatedType} object representing the potentially
+     *     annotated type that this type is a member of, or {@code null}
+     * @throws TypeNotPresentException if the owner type
+     *     refers to a non-existent type declaration
+     * @throws MalformedParameterizedTypeException if the owner type
+     *     refers to a parameterized type that cannot be instantiated
+     *     for any reason
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java	Tue Dec 22 13:41:12 2015 -0800
@@ -36,6 +36,37 @@
 public interface AnnotatedType extends AnnotatedElement {
 
     /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+     *     top-level type, or a local or anonymous class, or a primitive type, or
+     *     void.
+     *
+     * <p>Returns {@code null} if this {@code AnnotatedType} is an instance of
+     *     {@code AnnotatedArrayType}, {@code AnnotatedTypeVariable}, or
+     *     {@code AnnotatedWildcardType}.
+     *
+     * @implSpec
+     * This default implementation returns {@code null} and performs no other
+     * action.
+     *
+     * @return an {@code AnnotatedType} object representing the potentially
+     *     annotated type that this type is a member of, or {@code null}
+     * @throws TypeNotPresentException if the owner type
+     *     refers to a non-existent type declaration
+     * @throws MalformedParameterizedTypeException if the owner type
+     *     refers to a parameterized type that cannot be instantiated
+     *     for any reason
+     *
+     * @since 1.9
+     */
+    default AnnotatedType getAnnotatedOwnerType() {
+        return null;
+    }
+
+    /**
      * Returns the underlying type that this annotated type represents.
      *
      * @return the type this annotated type represents
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Tue Dec 22 13:41:12 2015 -0800
@@ -43,4 +43,19 @@
      * @see TypeVariable#getBounds()
      */
     AnnotatedType[] getAnnotatedBounds();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedTypeVariable}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Tue Dec 22 13:41:12 2015 -0800
@@ -54,4 +54,19 @@
      * @see WildcardType#getUpperBounds()
      */
     AnnotatedType[] getAnnotatedUpperBounds();
+
+    /**
+     * Returns the potentially annotated type that this type is a member of, if
+     * this type represents a nested type. For example, if this type is
+     * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+     *
+     * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+     *     of {@code AnnotatedWildcardType}.
+     *
+     * @return {@code null}
+     *
+     * @since 1.9
+     */
+    @Override
+    AnnotatedType getAnnotatedOwnerType();
 }
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Tue Dec 22 13:41:12 2015 -0800
@@ -34,7 +34,6 @@
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.BiFunction;
-import sun.misc.ProxyGenerator;
 import sun.misc.VM;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Tue Dec 22 13:41:12 2015 -0800
@@ -0,0 +1,2031 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import sun.security.action.GetBooleanAction;
+
+/**
+ * ProxyGenerator contains the code to generate a dynamic proxy class
+ * for the java.lang.reflect.Proxy API.
+ *
+ * The external interfaces to ProxyGenerator is the static
+ * "generateProxyClass" method.
+ *
+ * @author      Peter Jones
+ * @since       1.3
+ */
+class ProxyGenerator {
+    /*
+     * In the comments below, "JVMS" refers to The Java Virtual Machine
+     * Specification Second Edition and "JLS" refers to the original
+     * version of The Java Language Specification, unless otherwise
+     * specified.
+     */
+
+    /* generate 1.5-era class file version */
+    private static final int CLASSFILE_MAJOR_VERSION = 49;
+    private static final int CLASSFILE_MINOR_VERSION = 0;
+
+    /*
+     * beginning of constants copied from
+     * sun.tools.java.RuntimeConstants (which no longer exists):
+     */
+
+    /* constant pool tags */
+    private static final int CONSTANT_UTF8              = 1;
+    private static final int CONSTANT_UNICODE           = 2;
+    private static final int CONSTANT_INTEGER           = 3;
+    private static final int CONSTANT_FLOAT             = 4;
+    private static final int CONSTANT_LONG              = 5;
+    private static final int CONSTANT_DOUBLE            = 6;
+    private static final int CONSTANT_CLASS             = 7;
+    private static final int CONSTANT_STRING            = 8;
+    private static final int CONSTANT_FIELD             = 9;
+    private static final int CONSTANT_METHOD            = 10;
+    private static final int CONSTANT_INTERFACEMETHOD   = 11;
+    private static final int CONSTANT_NAMEANDTYPE       = 12;
+
+    /* access and modifier flags */
+    private static final int ACC_PUBLIC                 = 0x00000001;
+    private static final int ACC_PRIVATE                = 0x00000002;
+//  private static final int ACC_PROTECTED              = 0x00000004;
+    private static final int ACC_STATIC                 = 0x00000008;
+    private static final int ACC_FINAL                  = 0x00000010;
+//  private static final int ACC_SYNCHRONIZED           = 0x00000020;
+//  private static final int ACC_VOLATILE               = 0x00000040;
+//  private static final int ACC_TRANSIENT              = 0x00000080;
+//  private static final int ACC_NATIVE                 = 0x00000100;
+//  private static final int ACC_INTERFACE              = 0x00000200;
+//  private static final int ACC_ABSTRACT               = 0x00000400;
+    private static final int ACC_SUPER                  = 0x00000020;
+//  private static final int ACC_STRICT                 = 0x00000800;
+
+    /* opcodes */
+//  private static final int opc_nop                    = 0;
+    private static final int opc_aconst_null            = 1;
+//  private static final int opc_iconst_m1              = 2;
+    private static final int opc_iconst_0               = 3;
+//  private static final int opc_iconst_1               = 4;
+//  private static final int opc_iconst_2               = 5;
+//  private static final int opc_iconst_3               = 6;
+//  private static final int opc_iconst_4               = 7;
+//  private static final int opc_iconst_5               = 8;
+//  private static final int opc_lconst_0               = 9;
+//  private static final int opc_lconst_1               = 10;
+//  private static final int opc_fconst_0               = 11;
+//  private static final int opc_fconst_1               = 12;
+//  private static final int opc_fconst_2               = 13;
+//  private static final int opc_dconst_0               = 14;
+//  private static final int opc_dconst_1               = 15;
+    private static final int opc_bipush                 = 16;
+    private static final int opc_sipush                 = 17;
+    private static final int opc_ldc                    = 18;
+    private static final int opc_ldc_w                  = 19;
+//  private static final int opc_ldc2_w                 = 20;
+    private static final int opc_iload                  = 21;
+    private static final int opc_lload                  = 22;
+    private static final int opc_fload                  = 23;
+    private static final int opc_dload                  = 24;
+    private static final int opc_aload                  = 25;
+    private static final int opc_iload_0                = 26;
+//  private static final int opc_iload_1                = 27;
+//  private static final int opc_iload_2                = 28;
+//  private static final int opc_iload_3                = 29;
+    private static final int opc_lload_0                = 30;
+//  private static final int opc_lload_1                = 31;
+//  private static final int opc_lload_2                = 32;
+//  private static final int opc_lload_3                = 33;
+    private static final int opc_fload_0                = 34;
+//  private static final int opc_fload_1                = 35;
+//  private static final int opc_fload_2                = 36;
+//  private static final int opc_fload_3                = 37;
+    private static final int opc_dload_0                = 38;
+//  private static final int opc_dload_1                = 39;
+//  private static final int opc_dload_2                = 40;
+//  private static final int opc_dload_3                = 41;
+    private static final int opc_aload_0                = 42;
+//  private static final int opc_aload_1                = 43;
+//  private static final int opc_aload_2                = 44;
+//  private static final int opc_aload_3                = 45;
+//  private static final int opc_iaload                 = 46;
+//  private static final int opc_laload                 = 47;
+//  private static final int opc_faload                 = 48;
+//  private static final int opc_daload                 = 49;
+//  private static final int opc_aaload                 = 50;
+//  private static final int opc_baload                 = 51;
+//  private static final int opc_caload                 = 52;
+//  private static final int opc_saload                 = 53;
+//  private static final int opc_istore                 = 54;
+//  private static final int opc_lstore                 = 55;
+//  private static final int opc_fstore                 = 56;
+//  private static final int opc_dstore                 = 57;
+    private static final int opc_astore                 = 58;
+//  private static final int opc_istore_0               = 59;
+//  private static final int opc_istore_1               = 60;
+//  private static final int opc_istore_2               = 61;
+//  private static final int opc_istore_3               = 62;
+//  private static final int opc_lstore_0               = 63;
+//  private static final int opc_lstore_1               = 64;
+//  private static final int opc_lstore_2               = 65;
+//  private static final int opc_lstore_3               = 66;
+//  private static final int opc_fstore_0               = 67;
+//  private static final int opc_fstore_1               = 68;
+//  private static final int opc_fstore_2               = 69;
+//  private static final int opc_fstore_3               = 70;
+//  private static final int opc_dstore_0               = 71;
+//  private static final int opc_dstore_1               = 72;
+//  private static final int opc_dstore_2               = 73;
+//  private static final int opc_dstore_3               = 74;
+    private static final int opc_astore_0               = 75;
+//  private static final int opc_astore_1               = 76;
+//  private static final int opc_astore_2               = 77;
+//  private static final int opc_astore_3               = 78;
+//  private static final int opc_iastore                = 79;
+//  private static final int opc_lastore                = 80;
+//  private static final int opc_fastore                = 81;
+//  private static final int opc_dastore                = 82;
+    private static final int opc_aastore                = 83;
+//  private static final int opc_bastore                = 84;
+//  private static final int opc_castore                = 85;
+//  private static final int opc_sastore                = 86;
+    private static final int opc_pop                    = 87;
+//  private static final int opc_pop2                   = 88;
+    private static final int opc_dup                    = 89;
+//  private static final int opc_dup_x1                 = 90;
+//  private static final int opc_dup_x2                 = 91;
+//  private static final int opc_dup2                   = 92;
+//  private static final int opc_dup2_x1                = 93;
+//  private static final int opc_dup2_x2                = 94;
+//  private static final int opc_swap                   = 95;
+//  private static final int opc_iadd                   = 96;
+//  private static final int opc_ladd                   = 97;
+//  private static final int opc_fadd                   = 98;
+//  private static final int opc_dadd                   = 99;
+//  private static final int opc_isub                   = 100;
+//  private static final int opc_lsub                   = 101;
+//  private static final int opc_fsub                   = 102;
+//  private static final int opc_dsub                   = 103;
+//  private static final int opc_imul                   = 104;
+//  private static final int opc_lmul                   = 105;
+//  private static final int opc_fmul                   = 106;
+//  private static final int opc_dmul                   = 107;
+//  private static final int opc_idiv                   = 108;
+//  private static final int opc_ldiv                   = 109;
+//  private static final int opc_fdiv                   = 110;
+//  private static final int opc_ddiv                   = 111;
+//  private static final int opc_irem                   = 112;
+//  private static final int opc_lrem                   = 113;
+//  private static final int opc_frem                   = 114;
+//  private static final int opc_drem                   = 115;
+//  private static final int opc_ineg                   = 116;
+//  private static final int opc_lneg                   = 117;
+//  private static final int opc_fneg                   = 118;
+//  private static final int opc_dneg                   = 119;
+//  private static final int opc_ishl                   = 120;
+//  private static final int opc_lshl                   = 121;
+//  private static final int opc_ishr                   = 122;
+//  private static final int opc_lshr                   = 123;
+//  private static final int opc_iushr                  = 124;
+//  private static final int opc_lushr                  = 125;
+//  private static final int opc_iand                   = 126;
+//  private static final int opc_land                   = 127;
+//  private static final int opc_ior                    = 128;
+//  private static final int opc_lor                    = 129;
+//  private static final int opc_ixor                   = 130;
+//  private static final int opc_lxor                   = 131;
+//  private static final int opc_iinc                   = 132;
+//  private static final int opc_i2l                    = 133;
+//  private static final int opc_i2f                    = 134;
+//  private static final int opc_i2d                    = 135;
+//  private static final int opc_l2i                    = 136;
+//  private static final int opc_l2f                    = 137;
+//  private static final int opc_l2d                    = 138;
+//  private static final int opc_f2i                    = 139;
+//  private static final int opc_f2l                    = 140;
+//  private static final int opc_f2d                    = 141;
+//  private static final int opc_d2i                    = 142;
+//  private static final int opc_d2l                    = 143;
+//  private static final int opc_d2f                    = 144;
+//  private static final int opc_i2b                    = 145;
+//  private static final int opc_i2c                    = 146;
+//  private static final int opc_i2s                    = 147;
+//  private static final int opc_lcmp                   = 148;
+//  private static final int opc_fcmpl                  = 149;
+//  private static final int opc_fcmpg                  = 150;
+//  private static final int opc_dcmpl                  = 151;
+//  private static final int opc_dcmpg                  = 152;
+//  private static final int opc_ifeq                   = 153;
+//  private static final int opc_ifne                   = 154;
+//  private static final int opc_iflt                   = 155;
+//  private static final int opc_ifge                   = 156;
+//  private static final int opc_ifgt                   = 157;
+//  private static final int opc_ifle                   = 158;
+//  private static final int opc_if_icmpeq              = 159;
+//  private static final int opc_if_icmpne              = 160;
+//  private static final int opc_if_icmplt              = 161;
+//  private static final int opc_if_icmpge              = 162;
+//  private static final int opc_if_icmpgt              = 163;
+//  private static final int opc_if_icmple              = 164;
+//  private static final int opc_if_acmpeq              = 165;
+//  private static final int opc_if_acmpne              = 166;
+//  private static final int opc_goto                   = 167;
+//  private static final int opc_jsr                    = 168;
+//  private static final int opc_ret                    = 169;
+//  private static final int opc_tableswitch            = 170;
+//  private static final int opc_lookupswitch           = 171;
+    private static final int opc_ireturn                = 172;
+    private static final int opc_lreturn                = 173;
+    private static final int opc_freturn                = 174;
+    private static final int opc_dreturn                = 175;
+    private static final int opc_areturn                = 176;
+    private static final int opc_return                 = 177;
+    private static final int opc_getstatic              = 178;
+    private static final int opc_putstatic              = 179;
+    private static final int opc_getfield               = 180;
+//  private static final int opc_putfield               = 181;
+    private static final int opc_invokevirtual          = 182;
+    private static final int opc_invokespecial          = 183;
+    private static final int opc_invokestatic           = 184;
+    private static final int opc_invokeinterface        = 185;
+    private static final int opc_new                    = 187;
+//  private static final int opc_newarray               = 188;
+    private static final int opc_anewarray              = 189;
+//  private static final int opc_arraylength            = 190;
+    private static final int opc_athrow                 = 191;
+    private static final int opc_checkcast              = 192;
+//  private static final int opc_instanceof             = 193;
+//  private static final int opc_monitorenter           = 194;
+//  private static final int opc_monitorexit            = 195;
+    private static final int opc_wide                   = 196;
+//  private static final int opc_multianewarray         = 197;
+//  private static final int opc_ifnull                 = 198;
+//  private static final int opc_ifnonnull              = 199;
+//  private static final int opc_goto_w                 = 200;
+//  private static final int opc_jsr_w                  = 201;
+
+    // end of constants copied from sun.tools.java.RuntimeConstants
+
+    /** name of the superclass of proxy classes */
+    private static final String superclassName = "java/lang/reflect/Proxy";
+
+    /** name of field for storing a proxy instance's invocation handler */
+    private static final String handlerFieldName = "h";
+
+    /** debugging flag for saving generated class files */
+    private static final boolean saveGeneratedFiles =
+        java.security.AccessController.doPrivileged(
+            new GetBooleanAction(
+                "jdk.proxy.ProxyGenerator.saveGeneratedFiles")).booleanValue();
+
+    /**
+     * Generate a public proxy class given a name and a list of proxy interfaces.
+     */
+    static byte[] generateProxyClass(final String name,
+                                     Class<?>[] interfaces) {
+        return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
+    }
+
+    /**
+     * Generate a proxy class given a name and a list of proxy interfaces.
+     *
+     * @param name        the class name of the proxy class
+     * @param interfaces  proxy interfaces
+     * @param accessFlags access flags of the proxy class
+    */
+    static byte[] generateProxyClass(final String name,
+                                     Class<?>[] interfaces,
+                                     int accessFlags)
+    {
+        ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
+        final byte[] classFile = gen.generateClassFile();
+
+        if (saveGeneratedFiles) {
+            java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Void>() {
+                public Void run() {
+                    try {
+                        int i = name.lastIndexOf('.');
+                        Path path;
+                        if (i > 0) {
+                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+                            Files.createDirectories(dir);
+                            path = dir.resolve(name.substring(i+1, name.length()) + ".class");
+                        } else {
+                            path = Paths.get(name + ".class");
+                        }
+                        Files.write(path, classFile);
+                        return null;
+                    } catch (IOException e) {
+                        throw new InternalError(
+                            "I/O exception saving generated file: " + e);
+                    }
+                }
+            });
+        }
+
+        return classFile;
+    }
+
+    /* preloaded Method objects for methods in java.lang.Object */
+    private static Method hashCodeMethod;
+    private static Method equalsMethod;
+    private static Method toStringMethod;
+    static {
+        try {
+            hashCodeMethod = Object.class.getMethod("hashCode");
+            equalsMethod =
+                Object.class.getMethod("equals", new Class<?>[] { Object.class });
+            toStringMethod = Object.class.getMethod("toString");
+        } catch (NoSuchMethodException e) {
+            throw new NoSuchMethodError(e.getMessage());
+        }
+    }
+
+    /** name of proxy class */
+    private String className;
+
+    /** proxy interfaces */
+    private Class<?>[] interfaces;
+
+    /** proxy class access flags */
+    private int accessFlags;
+
+    /** constant pool of class being generated */
+    private ConstantPool cp = new ConstantPool();
+
+    /** FieldInfo struct for each field of generated class */
+    private List<FieldInfo> fields = new ArrayList<>();
+
+    /** MethodInfo struct for each method of generated class */
+    private List<MethodInfo> methods = new ArrayList<>();
+
+    /**
+     * maps method signature string to list of ProxyMethod objects for
+     * proxy methods with that signature
+     */
+    private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
+
+    /** count of ProxyMethod objects added to proxyMethods */
+    private int proxyMethodCount = 0;
+
+    /**
+     * Construct a ProxyGenerator to generate a proxy class with the
+     * specified name and for the given interfaces.
+     *
+     * A ProxyGenerator object contains the state for the ongoing
+     * generation of a particular proxy class.
+     */
+    private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
+        this.className = className;
+        this.interfaces = interfaces;
+        this.accessFlags = accessFlags;
+    }
+
+    /**
+     * Generate a class file for the proxy class.  This method drives the
+     * class file generation process.
+     */
+    private byte[] generateClassFile() {
+
+        /* ============================================================
+         * Step 1: Assemble ProxyMethod objects for all methods to
+         * generate proxy dispatching code for.
+         */
+
+        /*
+         * Record that proxy methods are needed for the hashCode, equals,
+         * and toString methods of java.lang.Object.  This is done before
+         * the methods from the proxy interfaces so that the methods from
+         * java.lang.Object take precedence over duplicate methods in the
+         * proxy interfaces.
+         */
+        addProxyMethod(hashCodeMethod, Object.class);
+        addProxyMethod(equalsMethod, Object.class);
+        addProxyMethod(toStringMethod, Object.class);
+
+        /*
+         * Now record all of the methods from the proxy interfaces, giving
+         * earlier interfaces precedence over later ones with duplicate
+         * methods.
+         */
+        for (Class<?> intf : interfaces) {
+            for (Method m : intf.getMethods()) {
+                addProxyMethod(m, intf);
+            }
+        }
+
+        /*
+         * For each set of proxy methods with the same signature,
+         * verify that the methods' return types are compatible.
+         */
+        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+            checkReturnTypes(sigmethods);
+        }
+
+        /* ============================================================
+         * Step 2: Assemble FieldInfo and MethodInfo structs for all of
+         * fields and methods in the class we are generating.
+         */
+        try {
+            methods.add(generateConstructor());
+
+            for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+                for (ProxyMethod pm : sigmethods) {
+
+                    // add static field for method's Method object
+                    fields.add(new FieldInfo(pm.methodFieldName,
+                        "Ljava/lang/reflect/Method;",
+                         ACC_PRIVATE | ACC_STATIC));
+
+                    // generate code for proxy method and add it
+                    methods.add(pm.generateMethod());
+                }
+            }
+
+            methods.add(generateStaticInitializer());
+
+        } catch (IOException e) {
+            throw new InternalError("unexpected I/O Exception", e);
+        }
+
+        if (methods.size() > 65535) {
+            throw new IllegalArgumentException("method limit exceeded");
+        }
+        if (fields.size() > 65535) {
+            throw new IllegalArgumentException("field limit exceeded");
+        }
+
+        /* ============================================================
+         * Step 3: Write the final class file.
+         */
+
+        /*
+         * Make sure that constant pool indexes are reserved for the
+         * following items before starting to write the final class file.
+         */
+        cp.getClass(dotToSlash(className));
+        cp.getClass(superclassName);
+        for (Class<?> intf: interfaces) {
+            cp.getClass(dotToSlash(intf.getName()));
+        }
+
+        /*
+         * Disallow new constant pool additions beyond this point, since
+         * we are about to write the final constant pool table.
+         */
+        cp.setReadOnly();
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        DataOutputStream dout = new DataOutputStream(bout);
+
+        try {
+            /*
+             * Write all the items of the "ClassFile" structure.
+             * See JVMS section 4.1.
+             */
+                                        // u4 magic;
+            dout.writeInt(0xCAFEBABE);
+                                        // u2 minor_version;
+            dout.writeShort(CLASSFILE_MINOR_VERSION);
+                                        // u2 major_version;
+            dout.writeShort(CLASSFILE_MAJOR_VERSION);
+
+            cp.write(dout);             // (write constant pool)
+
+                                        // u2 access_flags;
+            dout.writeShort(accessFlags);
+                                        // u2 this_class;
+            dout.writeShort(cp.getClass(dotToSlash(className)));
+                                        // u2 super_class;
+            dout.writeShort(cp.getClass(superclassName));
+
+                                        // u2 interfaces_count;
+            dout.writeShort(interfaces.length);
+                                        // u2 interfaces[interfaces_count];
+            for (Class<?> intf : interfaces) {
+                dout.writeShort(cp.getClass(
+                    dotToSlash(intf.getName())));
+            }
+
+                                        // u2 fields_count;
+            dout.writeShort(fields.size());
+                                        // field_info fields[fields_count];
+            for (FieldInfo f : fields) {
+                f.write(dout);
+            }
+
+                                        // u2 methods_count;
+            dout.writeShort(methods.size());
+                                        // method_info methods[methods_count];
+            for (MethodInfo m : methods) {
+                m.write(dout);
+            }
+
+                                         // u2 attributes_count;
+            dout.writeShort(0); // (no ClassFile attributes for proxy classes)
+
+        } catch (IOException e) {
+            throw new InternalError("unexpected I/O Exception", e);
+        }
+
+        return bout.toByteArray();
+    }
+
+    /**
+     * Add another method to be proxied, either by creating a new
+     * ProxyMethod object or augmenting an old one for a duplicate
+     * method.
+     *
+     * "fromClass" indicates the proxy interface that the method was
+     * found through, which may be different from (a subinterface of)
+     * the method's "declaring class".  Note that the first Method
+     * object passed for a given name and descriptor identifies the
+     * Method object (and thus the declaring class) that will be
+     * passed to the invocation handler's "invoke" method for a given
+     * set of duplicate methods.
+     */
+    private void addProxyMethod(Method m, Class<?> fromClass) {
+        String name = m.getName();
+        Class<?>[] parameterTypes = m.getParameterTypes();
+        Class<?> returnType = m.getReturnType();
+        Class<?>[] exceptionTypes = m.getExceptionTypes();
+
+        String sig = name + getParameterDescriptors(parameterTypes);
+        List<ProxyMethod> sigmethods = proxyMethods.get(sig);
+        if (sigmethods != null) {
+            for (ProxyMethod pm : sigmethods) {
+                if (returnType == pm.returnType) {
+                    /*
+                     * Found a match: reduce exception types to the
+                     * greatest set of exceptions that can thrown
+                     * compatibly with the throws clauses of both
+                     * overridden methods.
+                     */
+                    List<Class<?>> legalExceptions = new ArrayList<>();
+                    collectCompatibleTypes(
+                        exceptionTypes, pm.exceptionTypes, legalExceptions);
+                    collectCompatibleTypes(
+                        pm.exceptionTypes, exceptionTypes, legalExceptions);
+                    pm.exceptionTypes = new Class<?>[legalExceptions.size()];
+                    pm.exceptionTypes =
+                        legalExceptions.toArray(pm.exceptionTypes);
+                    return;
+                }
+            }
+        } else {
+            sigmethods = new ArrayList<>(3);
+            proxyMethods.put(sig, sigmethods);
+        }
+        sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
+                                       exceptionTypes, fromClass));
+    }
+
+    /**
+     * For a given set of proxy methods with the same signature, check
+     * that their return types are compatible according to the Proxy
+     * specification.
+     *
+     * Specifically, if there is more than one such method, then all
+     * of the return types must be reference types, and there must be
+     * one return type that is assignable to each of the rest of them.
+     */
+    private static void checkReturnTypes(List<ProxyMethod> methods) {
+        /*
+         * If there is only one method with a given signature, there
+         * cannot be a conflict.  This is the only case in which a
+         * primitive (or void) return type is allowed.
+         */
+        if (methods.size() < 2) {
+            return;
+        }
+
+        /*
+         * List of return types that are not yet known to be
+         * assignable from ("covered" by) any of the others.
+         */
+        LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
+
+    nextNewReturnType:
+        for (ProxyMethod pm : methods) {
+            Class<?> newReturnType = pm.returnType;
+            if (newReturnType.isPrimitive()) {
+                throw new IllegalArgumentException(
+                    "methods with same signature " +
+                    getFriendlyMethodSignature(pm.methodName,
+                                               pm.parameterTypes) +
+                    " but incompatible return types: " +
+                    newReturnType.getName() + " and others");
+            }
+            boolean added = false;
+
+            /*
+             * Compare the new return type to the existing uncovered
+             * return types.
+             */
+            ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
+            while (liter.hasNext()) {
+                Class<?> uncoveredReturnType = liter.next();
+
+                /*
+                 * If an existing uncovered return type is assignable
+                 * to this new one, then we can forget the new one.
+                 */
+                if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
+                    assert !added;
+                    continue nextNewReturnType;
+                }
+
+                /*
+                 * If the new return type is assignable to an existing
+                 * uncovered one, then should replace the existing one
+                 * with the new one (or just forget the existing one,
+                 * if the new one has already be put in the list).
+                 */
+                if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
+                    // (we can assume that each return type is unique)
+                    if (!added) {
+                        liter.set(newReturnType);
+                        added = true;
+                    } else {
+                        liter.remove();
+                    }
+                }
+            }
+
+            /*
+             * If we got through the list of existing uncovered return
+             * types without an assignability relationship, then add
+             * the new return type to the list of uncovered ones.
+             */
+            if (!added) {
+                uncoveredReturnTypes.add(newReturnType);
+            }
+        }
+
+        /*
+         * We shouldn't end up with more than one return type that is
+         * not assignable from any of the others.
+         */
+        if (uncoveredReturnTypes.size() > 1) {
+            ProxyMethod pm = methods.get(0);
+            throw new IllegalArgumentException(
+                "methods with same signature " +
+                getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
+                " but incompatible return types: " + uncoveredReturnTypes);
+        }
+    }
+
+    /**
+     * A FieldInfo object contains information about a particular field
+     * in the class being generated.  The class mirrors the data items of
+     * the "field_info" structure of the class file format (see JVMS 4.5).
+     */
+    private class FieldInfo {
+        public int accessFlags;
+        public String name;
+        public String descriptor;
+
+        public FieldInfo(String name, String descriptor, int accessFlags) {
+            this.name = name;
+            this.descriptor = descriptor;
+            this.accessFlags = accessFlags;
+
+            /*
+             * Make sure that constant pool indexes are reserved for the
+             * following items before starting to write the final class file.
+             */
+            cp.getUtf8(name);
+            cp.getUtf8(descriptor);
+        }
+
+        public void write(DataOutputStream out) throws IOException {
+            /*
+             * Write all the items of the "field_info" structure.
+             * See JVMS section 4.5.
+             */
+                                        // u2 access_flags;
+            out.writeShort(accessFlags);
+                                        // u2 name_index;
+            out.writeShort(cp.getUtf8(name));
+                                        // u2 descriptor_index;
+            out.writeShort(cp.getUtf8(descriptor));
+                                        // u2 attributes_count;
+            out.writeShort(0);  // (no field_info attributes for proxy classes)
+        }
+    }
+
+    /**
+     * An ExceptionTableEntry object holds values for the data items of
+     * an entry in the "exception_table" item of the "Code" attribute of
+     * "method_info" structures (see JVMS 4.7.3).
+     */
+    private static class ExceptionTableEntry {
+        public short startPc;
+        public short endPc;
+        public short handlerPc;
+        public short catchType;
+
+        public ExceptionTableEntry(short startPc, short endPc,
+                                   short handlerPc, short catchType)
+        {
+            this.startPc = startPc;
+            this.endPc = endPc;
+            this.handlerPc = handlerPc;
+            this.catchType = catchType;
+        }
+    };
+
+    /**
+     * A MethodInfo object contains information about a particular method
+     * in the class being generated.  This class mirrors the data items of
+     * the "method_info" structure of the class file format (see JVMS 4.6).
+     */
+    private class MethodInfo {
+        public int accessFlags;
+        public String name;
+        public String descriptor;
+        public short maxStack;
+        public short maxLocals;
+        public ByteArrayOutputStream code = new ByteArrayOutputStream();
+        public List<ExceptionTableEntry> exceptionTable =
+            new ArrayList<ExceptionTableEntry>();
+        public short[] declaredExceptions;
+
+        public MethodInfo(String name, String descriptor, int accessFlags) {
+            this.name = name;
+            this.descriptor = descriptor;
+            this.accessFlags = accessFlags;
+
+            /*
+             * Make sure that constant pool indexes are reserved for the
+             * following items before starting to write the final class file.
+             */
+            cp.getUtf8(name);
+            cp.getUtf8(descriptor);
+            cp.getUtf8("Code");
+            cp.getUtf8("Exceptions");
+        }
+
+        public void write(DataOutputStream out) throws IOException {
+            /*
+             * Write all the items of the "method_info" structure.
+             * See JVMS section 4.6.
+             */
+                                        // u2 access_flags;
+            out.writeShort(accessFlags);
+                                        // u2 name_index;
+            out.writeShort(cp.getUtf8(name));
+                                        // u2 descriptor_index;
+            out.writeShort(cp.getUtf8(descriptor));
+                                        // u2 attributes_count;
+            out.writeShort(2);  // (two method_info attributes:)
+
+            // Write "Code" attribute. See JVMS section 4.7.3.
+
+                                        // u2 attribute_name_index;
+            out.writeShort(cp.getUtf8("Code"));
+                                        // u4 attribute_length;
+            out.writeInt(12 + code.size() + 8 * exceptionTable.size());
+                                        // u2 max_stack;
+            out.writeShort(maxStack);
+                                        // u2 max_locals;
+            out.writeShort(maxLocals);
+                                        // u2 code_length;
+            out.writeInt(code.size());
+                                        // u1 code[code_length];
+            code.writeTo(out);
+                                        // u2 exception_table_length;
+            out.writeShort(exceptionTable.size());
+            for (ExceptionTableEntry e : exceptionTable) {
+                                        // u2 start_pc;
+                out.writeShort(e.startPc);
+                                        // u2 end_pc;
+                out.writeShort(e.endPc);
+                                        // u2 handler_pc;
+                out.writeShort(e.handlerPc);
+                                        // u2 catch_type;
+                out.writeShort(e.catchType);
+            }
+                                        // u2 attributes_count;
+            out.writeShort(0);
+
+            // write "Exceptions" attribute.  See JVMS section 4.7.4.
+
+                                        // u2 attribute_name_index;
+            out.writeShort(cp.getUtf8("Exceptions"));
+                                        // u4 attributes_length;
+            out.writeInt(2 + 2 * declaredExceptions.length);
+                                        // u2 number_of_exceptions;
+            out.writeShort(declaredExceptions.length);
+                        // u2 exception_index_table[number_of_exceptions];
+            for (short value : declaredExceptions) {
+                out.writeShort(value);
+            }
+        }
+
+    }
+
+    /**
+     * A ProxyMethod object represents a proxy method in the proxy class
+     * being generated: a method whose implementation will encode and
+     * dispatch invocations to the proxy instance's invocation handler.
+     */
+    private class ProxyMethod {
+
+        public String methodName;
+        public Class<?>[] parameterTypes;
+        public Class<?> returnType;
+        public Class<?>[] exceptionTypes;
+        public Class<?> fromClass;
+        public String methodFieldName;
+
+        private ProxyMethod(String methodName, Class<?>[] parameterTypes,
+                            Class<?> returnType, Class<?>[] exceptionTypes,
+                            Class<?> fromClass)
+        {
+            this.methodName = methodName;
+            this.parameterTypes = parameterTypes;
+            this.returnType = returnType;
+            this.exceptionTypes = exceptionTypes;
+            this.fromClass = fromClass;
+            this.methodFieldName = "m" + proxyMethodCount++;
+        }
+
+        /**
+         * Return a MethodInfo object for this method, including generating
+         * the code and exception table entry.
+         */
+        private MethodInfo generateMethod() throws IOException {
+            String desc = getMethodDescriptor(parameterTypes, returnType);
+            MethodInfo minfo = new MethodInfo(methodName, desc,
+                ACC_PUBLIC | ACC_FINAL);
+
+            int[] parameterSlot = new int[parameterTypes.length];
+            int nextSlot = 1;
+            for (int i = 0; i < parameterSlot.length; i++) {
+                parameterSlot[i] = nextSlot;
+                nextSlot += getWordsPerType(parameterTypes[i]);
+            }
+            int localSlot0 = nextSlot;
+            short pc, tryBegin = 0, tryEnd;
+
+            DataOutputStream out = new DataOutputStream(minfo.code);
+
+            code_aload(0, out);
+
+            out.writeByte(opc_getfield);
+            out.writeShort(cp.getFieldRef(
+                superclassName,
+                handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
+
+            code_aload(0, out);
+
+            out.writeByte(opc_getstatic);
+            out.writeShort(cp.getFieldRef(
+                dotToSlash(className),
+                methodFieldName, "Ljava/lang/reflect/Method;"));
+
+            if (parameterTypes.length > 0) {
+
+                code_ipush(parameterTypes.length, out);
+
+                out.writeByte(opc_anewarray);
+                out.writeShort(cp.getClass("java/lang/Object"));
+
+                for (int i = 0; i < parameterTypes.length; i++) {
+
+                    out.writeByte(opc_dup);
+
+                    code_ipush(i, out);
+
+                    codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
+
+                    out.writeByte(opc_aastore);
+                }
+            } else {
+
+                out.writeByte(opc_aconst_null);
+            }
+
+            out.writeByte(opc_invokeinterface);
+            out.writeShort(cp.getInterfaceMethodRef(
+                "java/lang/reflect/InvocationHandler",
+                "invoke",
+                "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
+                    "[Ljava/lang/Object;)Ljava/lang/Object;"));
+            out.writeByte(4);
+            out.writeByte(0);
+
+            if (returnType == void.class) {
+
+                out.writeByte(opc_pop);
+
+                out.writeByte(opc_return);
+
+            } else {
+
+                codeUnwrapReturnValue(returnType, out);
+            }
+
+            tryEnd = pc = (short) minfo.code.size();
+
+            List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
+            if (catchList.size() > 0) {
+
+                for (Class<?> ex : catchList) {
+                    minfo.exceptionTable.add(new ExceptionTableEntry(
+                        tryBegin, tryEnd, pc,
+                        cp.getClass(dotToSlash(ex.getName()))));
+                }
+
+                out.writeByte(opc_athrow);
+
+                pc = (short) minfo.code.size();
+
+                minfo.exceptionTable.add(new ExceptionTableEntry(
+                    tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
+
+                code_astore(localSlot0, out);
+
+                out.writeByte(opc_new);
+                out.writeShort(cp.getClass(
+                    "java/lang/reflect/UndeclaredThrowableException"));
+
+                out.writeByte(opc_dup);
+
+                code_aload(localSlot0, out);
+
+                out.writeByte(opc_invokespecial);
+
+                out.writeShort(cp.getMethodRef(
+                    "java/lang/reflect/UndeclaredThrowableException",
+                    "<init>", "(Ljava/lang/Throwable;)V"));
+
+                out.writeByte(opc_athrow);
+            }
+
+            if (minfo.code.size() > 65535) {
+                throw new IllegalArgumentException("code size limit exceeded");
+            }
+
+            minfo.maxStack = 10;
+            minfo.maxLocals = (short) (localSlot0 + 1);
+            minfo.declaredExceptions = new short[exceptionTypes.length];
+            for (int i = 0; i < exceptionTypes.length; i++) {
+                minfo.declaredExceptions[i] = cp.getClass(
+                    dotToSlash(exceptionTypes[i].getName()));
+            }
+
+            return minfo;
+        }
+
+        /**
+         * Generate code for wrapping an argument of the given type
+         * whose value can be found at the specified local variable
+         * index, in order for it to be passed (as an Object) to the
+         * invocation handler's "invoke" method.  The code is written
+         * to the supplied stream.
+         */
+        private void codeWrapArgument(Class<?> type, int slot,
+                                      DataOutputStream out)
+            throws IOException
+        {
+            if (type.isPrimitive()) {
+                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+                if (type == int.class ||
+                    type == boolean.class ||
+                    type == byte.class ||
+                    type == char.class ||
+                    type == short.class)
+                {
+                    code_iload(slot, out);
+                } else if (type == long.class) {
+                    code_lload(slot, out);
+                } else if (type == float.class) {
+                    code_fload(slot, out);
+                } else if (type == double.class) {
+                    code_dload(slot, out);
+                } else {
+                    throw new AssertionError();
+                }
+
+                out.writeByte(opc_invokestatic);
+                out.writeShort(cp.getMethodRef(
+                    prim.wrapperClassName,
+                    "valueOf", prim.wrapperValueOfDesc));
+
+            } else {
+
+                code_aload(slot, out);
+            }
+        }
+
+        /**
+         * Generate code for unwrapping a return value of the given
+         * type from the invocation handler's "invoke" method (as type
+         * Object) to its correct type.  The code is written to the
+         * supplied stream.
+         */
+        private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out)
+            throws IOException
+        {
+            if (type.isPrimitive()) {
+                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+                out.writeByte(opc_checkcast);
+                out.writeShort(cp.getClass(prim.wrapperClassName));
+
+                out.writeByte(opc_invokevirtual);
+                out.writeShort(cp.getMethodRef(
+                    prim.wrapperClassName,
+                    prim.unwrapMethodName, prim.unwrapMethodDesc));
+
+                if (type == int.class ||
+                    type == boolean.class ||
+                    type == byte.class ||
+                    type == char.class ||
+                    type == short.class)
+                {
+                    out.writeByte(opc_ireturn);
+                } else if (type == long.class) {
+                    out.writeByte(opc_lreturn);
+                } else if (type == float.class) {
+                    out.writeByte(opc_freturn);
+                } else if (type == double.class) {
+                    out.writeByte(opc_dreturn);
+                } else {
+                    throw new AssertionError();
+                }
+
+            } else {
+
+                out.writeByte(opc_checkcast);
+                out.writeShort(cp.getClass(dotToSlash(type.getName())));
+
+                out.writeByte(opc_areturn);
+            }
+        }
+
+        /**
+         * Generate code for initializing the static field that stores
+         * the Method object for this proxy method.  The code is written
+         * to the supplied stream.
+         */
+        private void codeFieldInitialization(DataOutputStream out)
+            throws IOException
+        {
+            codeClassForName(fromClass, out);
+
+            code_ldc(cp.getString(methodName), out);
+
+            code_ipush(parameterTypes.length, out);
+
+            out.writeByte(opc_anewarray);
+            out.writeShort(cp.getClass("java/lang/Class"));
+
+            for (int i = 0; i < parameterTypes.length; i++) {
+
+                out.writeByte(opc_dup);
+
+                code_ipush(i, out);
+
+                if (parameterTypes[i].isPrimitive()) {
+                    PrimitiveTypeInfo prim =
+                        PrimitiveTypeInfo.get(parameterTypes[i]);
+
+                    out.writeByte(opc_getstatic);
+                    out.writeShort(cp.getFieldRef(
+                        prim.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
+
+                } else {
+                    codeClassForName(parameterTypes[i], out);
+                }
+
+                out.writeByte(opc_aastore);
+            }
+
+            out.writeByte(opc_invokevirtual);
+            out.writeShort(cp.getMethodRef(
+                "java/lang/Class",
+                "getMethod",
+                "(Ljava/lang/String;[Ljava/lang/Class;)" +
+                "Ljava/lang/reflect/Method;"));
+
+            out.writeByte(opc_putstatic);
+            out.writeShort(cp.getFieldRef(
+                dotToSlash(className),
+                methodFieldName, "Ljava/lang/reflect/Method;"));
+        }
+    }
+
+    /**
+     * Generate the constructor method for the proxy class.
+     */
+    private MethodInfo generateConstructor() throws IOException {
+        MethodInfo minfo = new MethodInfo(
+            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
+            ACC_PUBLIC);
+
+        DataOutputStream out = new DataOutputStream(minfo.code);
+
+        code_aload(0, out);
+
+        code_aload(1, out);
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            superclassName,
+            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
+
+        out.writeByte(opc_return);
+
+        minfo.maxStack = 10;
+        minfo.maxLocals = 2;
+        minfo.declaredExceptions = new short[0];
+
+        return minfo;
+    }
+
+    /**
+     * Generate the static initializer method for the proxy class.
+     */
+    private MethodInfo generateStaticInitializer() throws IOException {
+        MethodInfo minfo = new MethodInfo(
+            "<clinit>", "()V", ACC_STATIC);
+
+        int localSlot0 = 1;
+        short pc, tryBegin = 0, tryEnd;
+
+        DataOutputStream out = new DataOutputStream(minfo.code);
+
+        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+            for (ProxyMethod pm : sigmethods) {
+                pm.codeFieldInitialization(out);
+            }
+        }
+
+        out.writeByte(opc_return);
+
+        tryEnd = pc = (short) minfo.code.size();
+
+        minfo.exceptionTable.add(new ExceptionTableEntry(
+            tryBegin, tryEnd, pc,
+            cp.getClass("java/lang/NoSuchMethodException")));
+
+        code_astore(localSlot0, out);
+
+        out.writeByte(opc_new);
+        out.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
+
+        out.writeByte(opc_dup);
+
+        code_aload(localSlot0, out);
+
+        out.writeByte(opc_invokevirtual);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
+
+        out.writeByte(opc_athrow);
+
+        pc = (short) minfo.code.size();
+
+        minfo.exceptionTable.add(new ExceptionTableEntry(
+            tryBegin, tryEnd, pc,
+            cp.getClass("java/lang/ClassNotFoundException")));
+
+        code_astore(localSlot0, out);
+
+        out.writeByte(opc_new);
+        out.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
+
+        out.writeByte(opc_dup);
+
+        code_aload(localSlot0, out);
+
+        out.writeByte(opc_invokevirtual);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+        out.writeByte(opc_invokespecial);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/NoClassDefFoundError",
+            "<init>", "(Ljava/lang/String;)V"));
+
+        out.writeByte(opc_athrow);
+
+        if (minfo.code.size() > 65535) {
+            throw new IllegalArgumentException("code size limit exceeded");
+        }
+
+        minfo.maxStack = 10;
+        minfo.maxLocals = (short) (localSlot0 + 1);
+        minfo.declaredExceptions = new short[0];
+
+        return minfo;
+    }
+
+
+    /*
+     * =============== Code Generation Utility Methods ===============
+     */
+
+    /*
+     * The following methods generate code for the load or store operation
+     * indicated by their name for the given local variable.  The code is
+     * written to the supplied stream.
+     */
+
+    private void code_iload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out);
+    }
+
+    private void code_lload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out);
+    }
+
+    private void code_fload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out);
+    }
+
+    private void code_dload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out);
+    }
+
+    private void code_aload(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out);
+    }
+
+//  private void code_istore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
+//  }
+
+//  private void code_lstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
+//  }
+
+//  private void code_fstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
+//  }
+
+//  private void code_dstore(int lvar, DataOutputStream out)
+//      throws IOException
+//  {
+//      codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
+//  }
+
+    private void code_astore(int lvar, DataOutputStream out)
+        throws IOException
+    {
+        codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out);
+    }
+
+    /**
+     * Generate code for a load or store instruction for the given local
+     * variable.  The code is written to the supplied stream.
+     *
+     * "opcode" indicates the opcode form of the desired load or store
+     * instruction that takes an explicit local variable index, and
+     * "opcode_0" indicates the corresponding form of the instruction
+     * with the implicit index 0.
+     */
+    private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
+                                    DataOutputStream out)
+        throws IOException
+    {
+        assert lvar >= 0 && lvar <= 0xFFFF;
+        if (lvar <= 3) {
+            out.writeByte(opcode_0 + lvar);
+        } else if (lvar <= 0xFF) {
+            out.writeByte(opcode);
+            out.writeByte(lvar & 0xFF);
+        } else {
+            /*
+             * Use the "wide" instruction modifier for local variable
+             * indexes that do not fit into an unsigned byte.
+             */
+            out.writeByte(opc_wide);
+            out.writeByte(opcode);
+            out.writeShort(lvar & 0xFFFF);
+        }
+    }
+
+    /**
+     * Generate code for an "ldc" instruction for the given constant pool
+     * index (the "ldc_w" instruction is used if the index does not fit
+     * into an unsigned byte).  The code is written to the supplied stream.
+     */
+    private void code_ldc(int index, DataOutputStream out)
+        throws IOException
+    {
+        assert index >= 0 && index <= 0xFFFF;
+        if (index <= 0xFF) {
+            out.writeByte(opc_ldc);
+            out.writeByte(index & 0xFF);
+        } else {
+            out.writeByte(opc_ldc_w);
+            out.writeShort(index & 0xFFFF);
+        }
+    }
+
+    /**
+     * Generate code to push a constant integer value on to the operand
+     * stack, using the "iconst_<i>", "bipush", or "sipush" instructions
+     * depending on the size of the value.  The code is written to the
+     * supplied stream.
+     */
+    private void code_ipush(int value, DataOutputStream out)
+        throws IOException
+    {
+        if (value >= -1 && value <= 5) {
+            out.writeByte(opc_iconst_0 + value);
+        } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+            out.writeByte(opc_bipush);
+            out.writeByte(value & 0xFF);
+        } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+            out.writeByte(opc_sipush);
+            out.writeShort(value & 0xFFFF);
+        } else {
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Generate code to invoke the Class.forName with the name of the given
+     * class to get its Class object at runtime.  The code is written to
+     * the supplied stream.  Note that the code generated by this method
+     * may caused the checked ClassNotFoundException to be thrown.
+     */
+    private void codeClassForName(Class<?> cl, DataOutputStream out)
+        throws IOException
+    {
+        code_ldc(cp.getString(cl.getName()), out);
+
+        out.writeByte(opc_invokestatic);
+        out.writeShort(cp.getMethodRef(
+            "java/lang/Class",
+            "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
+    }
+
+
+    /*
+     * ==================== General Utility Methods ====================
+     */
+
+    /**
+     * Convert a fully qualified class name that uses '.' as the package
+     * separator, the external representation used by the Java language
+     * and APIs, to a fully qualified class name that uses '/' as the
+     * package separator, the representation used in the class file
+     * format (see JVMS section 4.2).
+     */
+    private static String dotToSlash(String name) {
+        return name.replace('.', '/');
+    }
+
+    /**
+     * Return the "method descriptor" string for a method with the given
+     * parameter types and return type.  See JVMS section 4.3.3.
+     */
+    private static String getMethodDescriptor(Class<?>[] parameterTypes,
+                                              Class<?> returnType)
+    {
+        return getParameterDescriptors(parameterTypes) +
+            ((returnType == void.class) ? "V" : getFieldType(returnType));
+    }
+
+    /**
+     * Return the list of "parameter descriptor" strings enclosed in
+     * parentheses corresponding to the given parameter types (in other
+     * words, a method descriptor without a return descriptor).  This
+     * string is useful for constructing string keys for methods without
+     * regard to their return type.
+     */
+    private static String getParameterDescriptors(Class<?>[] parameterTypes) {
+        StringBuilder desc = new StringBuilder("(");
+        for (int i = 0; i < parameterTypes.length; i++) {
+            desc.append(getFieldType(parameterTypes[i]));
+        }
+        desc.append(')');
+        return desc.toString();
+    }
+
+    /**
+     * Return the "field type" string for the given type, appropriate for
+     * a field descriptor, a parameter descriptor, or a return descriptor
+     * other than "void".  See JVMS section 4.3.2.
+     */
+    private static String getFieldType(Class<?> type) {
+        if (type.isPrimitive()) {
+            return PrimitiveTypeInfo.get(type).baseTypeString;
+        } else if (type.isArray()) {
+            /*
+             * According to JLS 20.3.2, the getName() method on Class does
+             * return the VM type descriptor format for array classes (only);
+             * using that should be quicker than the otherwise obvious code:
+             *
+             *     return "[" + getTypeDescriptor(type.getComponentType());
+             */
+            return type.getName().replace('.', '/');
+        } else {
+            return "L" + dotToSlash(type.getName()) + ";";
+        }
+    }
+
+    /**
+     * Returns a human-readable string representing the signature of a
+     * method with the given name and parameter types.
+     */
+    private static String getFriendlyMethodSignature(String name,
+                                                     Class<?>[] parameterTypes)
+    {
+        StringBuilder sig = new StringBuilder(name);
+        sig.append('(');
+        for (int i = 0; i < parameterTypes.length; i++) {
+            if (i > 0) {
+                sig.append(',');
+            }
+            Class<?> parameterType = parameterTypes[i];
+            int dimensions = 0;
+            while (parameterType.isArray()) {
+                parameterType = parameterType.getComponentType();
+                dimensions++;
+            }
+            sig.append(parameterType.getName());
+            while (dimensions-- > 0) {
+                sig.append("[]");
+            }
+        }
+        sig.append(')');
+        return sig.toString();
+    }
+
+    /**
+     * Return the number of abstract "words", or consecutive local variable
+     * indexes, required to contain a value of the given type.  See JVMS
+     * section 3.6.1.
+     *
+     * Note that the original version of the JVMS contained a definition of
+     * this abstract notion of a "word" in section 3.4, but that definition
+     * was removed for the second edition.
+     */
+    private static int getWordsPerType(Class<?> type) {
+        if (type == long.class || type == double.class) {
+            return 2;
+        } else {
+            return 1;
+        }
+    }
+
+    /**
+     * Add to the given list all of the types in the "from" array that
+     * are not already contained in the list and are assignable to at
+     * least one of the types in the "with" array.
+     *
+     * This method is useful for computing the greatest common set of
+     * declared exceptions from duplicate methods inherited from
+     * different interfaces.
+     */
+    private static void collectCompatibleTypes(Class<?>[] from,
+                                               Class<?>[] with,
+                                               List<Class<?>> list)
+    {
+        for (Class<?> fc: from) {
+            if (!list.contains(fc)) {
+                for (Class<?> wc: with) {
+                    if (wc.isAssignableFrom(fc)) {
+                        list.add(fc);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Given the exceptions declared in the throws clause of a proxy method,
+     * compute the exceptions that need to be caught from the invocation
+     * handler's invoke method and rethrown intact in the method's
+     * implementation before catching other Throwables and wrapping them
+     * in UndeclaredThrowableExceptions.
+     *
+     * The exceptions to be caught are returned in a List object.  Each
+     * exception in the returned list is guaranteed to not be a subclass of
+     * any of the other exceptions in the list, so the catch blocks for
+     * these exceptions may be generated in any order relative to each other.
+     *
+     * Error and RuntimeException are each always contained by the returned
+     * list (if none of their superclasses are contained), since those
+     * unchecked exceptions should always be rethrown intact, and thus their
+     * subclasses will never appear in the returned list.
+     *
+     * The returned List will be empty if java.lang.Throwable is in the
+     * given list of declared exceptions, indicating that no exceptions
+     * need to be caught.
+     */
+    private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
+        List<Class<?>> uniqueList = new ArrayList<>();
+                                                // unique exceptions to catch
+
+        uniqueList.add(Error.class);            // always catch/rethrow these
+        uniqueList.add(RuntimeException.class);
+
+    nextException:
+        for (Class<?> ex: exceptions) {
+            if (ex.isAssignableFrom(Throwable.class)) {
+                /*
+                 * If Throwable is declared to be thrown by the proxy method,
+                 * then no catch blocks are necessary, because the invoke
+                 * can, at most, throw Throwable anyway.
+                 */
+                uniqueList.clear();
+                break;
+            } else if (!Throwable.class.isAssignableFrom(ex)) {
+                /*
+                 * Ignore types that cannot be thrown by the invoke method.
+                 */
+                continue;
+            }
+            /*
+             * Compare this exception against the current list of
+             * exceptions that need to be caught:
+             */
+            for (int j = 0; j < uniqueList.size();) {
+                Class<?> ex2 = uniqueList.get(j);
+                if (ex2.isAssignableFrom(ex)) {
+                    /*
+                     * if a superclass of this exception is already on
+                     * the list to catch, then ignore this one and continue;
+                     */
+                    continue nextException;
+                } else if (ex.isAssignableFrom(ex2)) {
+                    /*
+                     * if a subclass of this exception is on the list
+                     * to catch, then remove it;
+                     */
+                    uniqueList.remove(j);
+                } else {
+                    j++;        // else continue comparing.
+                }
+            }
+            // This exception is unique (so far): add it to the list to catch.
+            uniqueList.add(ex);
+        }
+        return uniqueList;
+    }
+
+    /**
+     * A PrimitiveTypeInfo object contains assorted information about
+     * a primitive type in its public fields.  The struct for a particular
+     * primitive type can be obtained using the static "get" method.
+     */
+    private static class PrimitiveTypeInfo {
+
+        /** "base type" used in various descriptors (see JVMS section 4.3.2) */
+        public String baseTypeString;
+
+        /** name of corresponding wrapper class */
+        public String wrapperClassName;
+
+        /** method descriptor for wrapper class "valueOf" factory method */
+        public String wrapperValueOfDesc;
+
+        /** name of wrapper class method for retrieving primitive value */
+        public String unwrapMethodName;
+
+        /** descriptor of same method */
+        public String unwrapMethodDesc;
+
+        private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>();
+        static {
+            add(byte.class, Byte.class);
+            add(char.class, Character.class);
+            add(double.class, Double.class);
+            add(float.class, Float.class);
+            add(int.class, Integer.class);
+            add(long.class, Long.class);
+            add(short.class, Short.class);
+            add(boolean.class, Boolean.class);
+        }
+
+        private static void add(Class<?> primitiveClass, Class<?> wrapperClass) {
+            table.put(primitiveClass,
+                      new PrimitiveTypeInfo(primitiveClass, wrapperClass));
+        }
+
+        private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) {
+            assert primitiveClass.isPrimitive();
+
+            baseTypeString =
+                Array.newInstance(primitiveClass, 0)
+                .getClass().getName().substring(1);
+            wrapperClassName = dotToSlash(wrapperClass.getName());
+            wrapperValueOfDesc =
+                "(" + baseTypeString + ")L" + wrapperClassName + ";";
+            unwrapMethodName = primitiveClass.getName() + "Value";
+            unwrapMethodDesc = "()" + baseTypeString;
+        }
+
+        public static PrimitiveTypeInfo get(Class<?> cl) {
+            return table.get(cl);
+        }
+    }
+
+
+    /**
+     * A ConstantPool object represents the constant pool of a class file
+     * being generated.  This representation of a constant pool is designed
+     * specifically for use by ProxyGenerator; in particular, it assumes
+     * that constant pool entries will not need to be resorted (for example,
+     * by their type, as the Java compiler does), so that the final index
+     * value can be assigned and used when an entry is first created.
+     *
+     * Note that new entries cannot be created after the constant pool has
+     * been written to a class file.  To prevent such logic errors, a
+     * ConstantPool instance can be marked "read only", so that further
+     * attempts to add new entries will fail with a runtime exception.
+     *
+     * See JVMS section 4.4 for more information about the constant pool
+     * of a class file.
+     */
+    private static class ConstantPool {
+
+        /**
+         * list of constant pool entries, in constant pool index order.
+         *
+         * This list is used when writing the constant pool to a stream
+         * and for assigning the next index value.  Note that element 0
+         * of this list corresponds to constant pool index 1.
+         */
+        private List<Entry> pool = new ArrayList<>(32);
+
+        /**
+         * maps constant pool data of all types to constant pool indexes.
+         *
+         * This map is used to look up the index of an existing entry for
+         * values of all types.
+         */
+        private Map<Object,Short> map = new HashMap<>(16);
+
+        /** true if no new constant pool entries may be added */
+        private boolean readOnly = false;
+
+        /**
+         * Get or assign the index for a CONSTANT_Utf8 entry.
+         */
+        public short getUtf8(String s) {
+            if (s == null) {
+                throw new NullPointerException();
+            }
+            return getValue(s);
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Integer entry.
+         */
+        public short getInteger(int i) {
+            return getValue(i);
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Float entry.
+         */
+        public short getFloat(float f) {
+            return getValue(new Float(f));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_Class entry.
+         */
+        public short getClass(String name) {
+            short utf8Index = getUtf8(name);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_CLASS, utf8Index));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_String entry.
+         */
+        public short getString(String s) {
+            short utf8Index = getUtf8(s);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_STRING, utf8Index));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_FieldRef entry.
+         */
+        public short getFieldRef(String className,
+                                 String name, String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_FIELD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_MethodRef entry.
+         */
+        public short getMethodRef(String className,
+                                  String name, String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_METHOD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
+         */
+        public short getInterfaceMethodRef(String className, String name,
+                                           String descriptor)
+        {
+            short classIndex = getClass(className);
+            short nameAndTypeIndex = getNameAndType(name, descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
+        }
+
+        /**
+         * Get or assign the index for a CONSTANT_NameAndType entry.
+         */
+        public short getNameAndType(String name, String descriptor) {
+            short nameIndex = getUtf8(name);
+            short descriptorIndex = getUtf8(descriptor);
+            return getIndirect(new IndirectEntry(
+                CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
+        }
+
+        /**
+         * Set this ConstantPool instance to be "read only".
+         *
+         * After this method has been called, further requests to get
+         * an index for a non-existent entry will cause an InternalError
+         * to be thrown instead of creating of the entry.
+         */
+        public void setReadOnly() {
+            readOnly = true;
+        }
+
+        /**
+         * Write this constant pool to a stream as part of
+         * the class file format.
+         *
+         * This consists of writing the "constant_pool_count" and
+         * "constant_pool[]" items of the "ClassFile" structure, as
+         * described in JVMS section 4.1.
+         */
+        public void write(OutputStream out) throws IOException {
+            DataOutputStream dataOut = new DataOutputStream(out);
+
+            // constant_pool_count: number of entries plus one
+            dataOut.writeShort(pool.size() + 1);
+
+            for (Entry e : pool) {
+                e.write(dataOut);
+            }
+        }
+
+        /**
+         * Add a new constant pool entry and return its index.
+         */
+        private short addEntry(Entry entry) {
+            pool.add(entry);
+            /*
+             * Note that this way of determining the index of the
+             * added entry is wrong if this pool supports
+             * CONSTANT_Long or CONSTANT_Double entries.
+             */
+            if (pool.size() >= 65535) {
+                throw new IllegalArgumentException(
+                    "constant pool size limit exceeded");
+            }
+            return (short) pool.size();
+        }
+
+        /**
+         * Get or assign the index for an entry of a type that contains
+         * a direct value.  The type of the given object determines the
+         * type of the desired entry as follows:
+         *
+         *      java.lang.String        CONSTANT_Utf8
+         *      java.lang.Integer       CONSTANT_Integer
+         *      java.lang.Float         CONSTANT_Float
+         *      java.lang.Long          CONSTANT_Long
+         *      java.lang.Double        CONSTANT_DOUBLE
+         */
+        private short getValue(Object key) {
+            Short index = map.get(key);
+            if (index != null) {
+                return index.shortValue();
+            } else {
+                if (readOnly) {
+                    throw new InternalError(
+                        "late constant pool addition: " + key);
+                }
+                short i = addEntry(new ValueEntry(key));
+                map.put(key, i);
+                return i;
+            }
+        }
+
+        /**
+         * Get or assign the index for an entry of a type that contains
+         * references to other constant pool entries.
+         */
+        private short getIndirect(IndirectEntry e) {
+            Short index = map.get(e);
+            if (index != null) {
+                return index.shortValue();
+            } else {
+                if (readOnly) {
+                    throw new InternalError("late constant pool addition");
+                }
+                short i = addEntry(e);
+                map.put(e, i);
+                return i;
+            }
+        }
+
+        /**
+         * Entry is the abstact superclass of all constant pool entry types
+         * that can be stored in the "pool" list; its purpose is to define a
+         * common method for writing constant pool entries to a class file.
+         */
+        private abstract static class Entry {
+            public abstract void write(DataOutputStream out)
+                throws IOException;
+        }
+
+        /**
+         * ValueEntry represents a constant pool entry of a type that
+         * contains a direct value (see the comments for the "getValue"
+         * method for a list of such types).
+         *
+         * ValueEntry objects are not used as keys for their entries in the
+         * Map "map", so no useful hashCode or equals methods are defined.
+         */
+        private static class ValueEntry extends Entry {
+            private Object value;
+
+            public ValueEntry(Object value) {
+                this.value = value;
+            }
+
+            public void write(DataOutputStream out) throws IOException {
+                if (value instanceof String) {
+                    out.writeByte(CONSTANT_UTF8);
+                    out.writeUTF((String) value);
+                } else if (value instanceof Integer) {
+                    out.writeByte(CONSTANT_INTEGER);
+                    out.writeInt(((Integer) value).intValue());
+                } else if (value instanceof Float) {
+                    out.writeByte(CONSTANT_FLOAT);
+                    out.writeFloat(((Float) value).floatValue());
+                } else if (value instanceof Long) {
+                    out.writeByte(CONSTANT_LONG);
+                    out.writeLong(((Long) value).longValue());
+                } else if (value instanceof Double) {
+                    out.writeDouble(CONSTANT_DOUBLE);
+                    out.writeDouble(((Double) value).doubleValue());
+                } else {
+                    throw new InternalError("bogus value entry: " + value);
+                }
+            }
+        }
+
+        /**
+         * IndirectEntry represents a constant pool entry of a type that
+         * references other constant pool entries, i.e., the following types:
+         *
+         *      CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
+         *      CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
+         *      CONSTANT_NameAndType.
+         *
+         * Each of these entry types contains either one or two indexes of
+         * other constant pool entries.
+         *
+         * IndirectEntry objects are used as the keys for their entries in
+         * the Map "map", so the hashCode and equals methods are overridden
+         * to allow matching.
+         */
+        private static class IndirectEntry extends Entry {
+            private int tag;
+            private short index0;
+            private short index1;
+
+            /**
+             * Construct an IndirectEntry for a constant pool entry type
+             * that contains one index of another entry.
+             */
+            public IndirectEntry(int tag, short index) {
+                this.tag = tag;
+                this.index0 = index;
+                this.index1 = 0;
+            }
+
+            /**
+             * Construct an IndirectEntry for a constant pool entry type
+             * that contains two indexes for other entries.
+             */
+            public IndirectEntry(int tag, short index0, short index1) {
+                this.tag = tag;
+                this.index0 = index0;
+                this.index1 = index1;
+            }
+
+            public void write(DataOutputStream out) throws IOException {
+                out.writeByte(tag);
+                out.writeShort(index0);
+                /*
+                 * If this entry type contains two indexes, write
+                 * out the second, too.
+                 */
+                if (tag == CONSTANT_FIELD ||
+                    tag == CONSTANT_METHOD ||
+                    tag == CONSTANT_INTERFACEMETHOD ||
+                    tag == CONSTANT_NAMEANDTYPE)
+                {
+                    out.writeShort(index1);
+                }
+            }
+
+            public int hashCode() {
+                return tag + index0 + index1;
+            }
+
+            public boolean equals(Object obj) {
+                if (obj instanceof IndirectEntry) {
+                    IndirectEntry other = (IndirectEntry) obj;
+                    if (tag == other.tag &&
+                        index0 == other.index0 && index1 == other.index1)
+                    {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+}
--- a/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java	Tue Dec 22 13:41:12 2015 -0800
@@ -27,7 +27,7 @@
 
 import java.io.IOException;
 
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.DerValue;
 
 /**
--- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java	Tue Dec 22 13:41:12 2015 -0800
@@ -31,7 +31,7 @@
 import java.util.*;
 import javax.security.auth.x500.X500Principal;
 
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.Debug;
 import sun.security.util.DerInputStream;
 import sun.security.util.DerValue;
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue Dec 22 13:41:12 2015 -0800
@@ -1856,6 +1856,7 @@
             if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
                 patternCharIndex == PATTERN_HOUR1 ||
                 (patternCharIndex == PATTERN_MONTH && count <= 2) ||
+                (patternCharIndex == PATTERN_MONTH_STANDALONE && count <= 2) ||
                 patternCharIndex == PATTERN_YEAR ||
                 patternCharIndex == PATTERN_WEEK_YEAR) {
                 // It would be good to unify this with the obeyCount logic below,
@@ -1976,6 +1977,20 @@
                 }
                 break parsing;
 
+            case PATTERN_MONTH_STANDALONE: // 'L'
+                if (count <= 2) {
+                    // Don't want to parse the month if it is a string
+                    // while pattern uses numeric style: L or LL
+                    //[we computed 'value' above.]
+                    calb.set(Calendar.MONTH, value - 1);
+                    return pos.index;
+                }
+                Map<String, Integer> maps = getDisplayNamesMap(field, locale);
+                if ((index = matchString(text, start, field, maps, calb)) > 0) {
+                    return index;
+                }
+                break parsing;
+
             case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
                 if (!isLenient()) {
                     // Validate the hour value in non-lenient
--- a/src/java.base/share/classes/java/time/Duration.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/time/Duration.java	Tue Dec 22 13:41:12 2015 -0800
@@ -997,6 +997,24 @@
      }
 
     /**
+     * Returns number of whole times a specified Duration occurs within this Duration.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param divisor the value to divide the duration by, positive or negative, not null
+     * @return number of whole times, rounded toward zero, a specified
+     *         {@code Duration} occurs within this Duration, may be negative
+     * @throws ArithmeticException if the divisor is zero, or if numeric overflow occurs
+     * @since 9
+     */
+    public long dividedBy(Duration divisor) {
+        Objects.requireNonNull(divisor, "divisor");
+        BigDecimal dividendBigD = toBigDecimalSeconds();
+        BigDecimal divisorBigD = divisor.toBigDecimalSeconds();
+        return dividendBigD.divideToIntegralValue(divisorBigD).longValueExact();
+    }
+
+    /**
      * Converts this duration to the total length in seconds and
      * fractional nanoseconds expressed as a {@code BigDecimal}.
      *
--- a/src/java.base/share/classes/java/util/AbstractMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/AbstractMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -304,9 +304,28 @@
      * Each of these fields are initialized to contain an instance of the
      * appropriate view the first time this view is requested.  The views are
      * stateless, so there's no reason to create more than one of each.
+     *
+     * <p>Since there is no synchronization performed while accessing these fields,
+     * it is expected that java.util.Map view classes using these fields have
+     * no non-final fields (or any fields at all except for outer-this). Adhering
+     * to this rule would make the races on these fields benign.
+     *
+     * <p>It is also imperative that implementations read the field only once,
+     * as in:
+     *
+     * <pre> {@code
+     * public Set<K> keySet() {
+     *   Set<K> ks = keySet;  // single racy read
+     *   if (ks == null) {
+     *     ks = new KeySet();
+     *     keySet = ks;
+     *   }
+     *   return ks;
+     * }
+     *}</pre>
      */
-    transient volatile Set<K>        keySet;
-    transient volatile Collection<V> values;
+    transient Set<K>        keySet;
+    transient Collection<V> values;
 
     /**
      * {@inheritDoc}
@@ -325,8 +344,9 @@
      * method will not all return the same set.
      */
     public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new AbstractSet<K>() {
                 public Iterator<K> iterator() {
                     return new Iterator<K>() {
                         private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -361,8 +381,9 @@
                     return AbstractMap.this.containsKey(k);
                 }
             };
+            keySet = ks;
         }
-        return keySet;
+        return ks;
     }
 
     /**
@@ -382,8 +403,9 @@
      * method will not all return the same collection.
      */
     public Collection<V> values() {
-        if (values == null) {
-            values = new AbstractCollection<V>() {
+        Collection<V> vals = values;
+        if (vals == null) {
+            vals = new AbstractCollection<V>() {
                 public Iterator<V> iterator() {
                     return new Iterator<V>() {
                         private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -418,8 +440,9 @@
                     return AbstractMap.this.containsValue(v);
                 }
             };
+            values = vals;
         }
-        return values;
+        return vals;
     }
 
     public abstract Set<Entry<K,V>> entrySet();
--- a/src/java.base/share/classes/java/util/Collections.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/Collections.java	Tue Dec 22 13:41:12 2015 -0800
@@ -5530,7 +5530,7 @@
      * @since  1.6
      */
     public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
-        return new AsLIFOQueue<>(deque);
+        return new AsLIFOQueue<>(Objects.requireNonNull(deque));
     }
 
     /**
--- a/src/java.base/share/classes/java/util/EnumMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/EnumMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -380,10 +380,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        if (ks != null)
-            return ks;
-        else
-            return keySet = new KeySet();
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -418,10 +419,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        if (vs != null)
-            return vs;
-        else
-            return values = new Values();
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/HashMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/HashMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -902,8 +902,12 @@
      * @return a set view of the keys contained in this map
      */
     public Set<K> keySet() {
-        Set<K> ks;
-        return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     final class KeySet extends AbstractSet<K> {
@@ -949,8 +953,12 @@
      * @return a view of the values contained in this map
      */
     public Collection<V> values() {
-        Collection<V> vs;
-        return (vs = values) == null ? (values = new Values()) : vs;
+        Collection<V> vs = values;
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     final class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/IdentityHashMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/IdentityHashMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -964,10 +964,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        if (ks != null)
-            return ks;
-        else
-            return keySet = new KeySet();
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -1069,10 +1070,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        if (vs != null)
-            return vs;
-        else
-            return values = new Values();
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/LinkedHashMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/LinkedHashMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -528,8 +528,12 @@
      * @return a set view of the keys contained in this map
      */
     public Set<K> keySet() {
-        Set<K> ks;
-        return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
+        Set<K> ks = keySet;
+        if (ks == null) {
+            ks = new LinkedKeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     final class LinkedKeySet extends AbstractSet<K> {
@@ -577,8 +581,12 @@
      * @return a view of the values contained in this map
      */
     public Collection<V> values() {
-        Collection<V> vs;
-        return (vs = values) == null ? (values = new LinkedValues()) : vs;
+        Collection<V> vs = values;
+        if (vs == null) {
+            vs = new LinkedValues();
+            values = vs;
+        }
+        return vs;
     }
 
     final class LinkedValues extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/TreeMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/TreeMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -852,7 +852,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        return (vs != null) ? vs : (values = new Values());
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     /**
--- a/src/java.base/share/classes/java/util/WeakHashMap.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/WeakHashMap.java	Tue Dec 22 13:41:12 2015 -0800
@@ -866,7 +866,11 @@
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
-        return (ks != null ? ks : (keySet = new KeySet()));
+        if (ks == null) {
+            ks = new KeySet();
+            keySet = ks;
+        }
+        return ks;
     }
 
     private class KeySet extends AbstractSet<K> {
@@ -915,7 +919,11 @@
      */
     public Collection<V> values() {
         Collection<V> vs = values;
-        return (vs != null) ? vs : (values = new Values());
+        if (vs == null) {
+            vs = new Values();
+            values = vs;
+        }
+        return vs;
     }
 
     private class Values extends AbstractCollection<V> {
--- a/src/java.base/share/classes/java/util/jar/JarFile.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/jar/JarFile.java	Tue Dec 22 13:41:12 2015 -0800
@@ -203,7 +203,10 @@
         return man;
     }
 
-    private native String[] getMetaInfEntryNames();
+    private String[] getMetaInfEntryNames() {
+        return jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess()
+                                              .getMetaInfEntryNames((ZipFile)this);
+    }
 
     /**
      * Returns the {@code JarEntry} for the given entry name or
--- a/src/java.base/share/classes/java/util/regex/Pattern.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java	Tue Dec 22 13:41:12 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -5814,7 +5814,7 @@
      */
     public Stream<String> splitAsStream(final CharSequence input) {
         class MatcherIterator implements Iterator<String> {
-            private final Matcher matcher;
+            private Matcher matcher;
             // The start position of the next sub-sequence of input
             // when current == input.length there are no more elements
             private int current;
@@ -5823,14 +5823,6 @@
             // > 0 if there are N next empty elements
             private int emptyElementCount;
 
-            MatcherIterator() {
-                this.matcher = matcher(input);
-                // If the input is an empty string then the result can only be a
-                // stream of the input.  Induce that by setting the empty
-                // element count to 1
-                this.emptyElementCount = input.length() == 0 ? 1 : 0;
-            }
-
             public String next() {
                 if (!hasNext())
                     throw new NoSuchElementException();
@@ -5846,6 +5838,13 @@
             }
 
             public boolean hasNext() {
+                if (matcher == null) {
+                    matcher = matcher(input);
+                    // If the input is an empty string then the result can only be a
+                    // stream of the input.  Induce that by setting the empty
+                    // element count to 1
+                    emptyElementCount = input.length() == 0 ? 1 : 0;
+                }
                 if (nextElement != null || emptyElementCount > 0)
                     return true;
 
--- a/src/java.base/share/classes/java/util/stream/Collectors.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/stream/Collectors.java	Tue Dec 22 13:41:12 2015 -0800
@@ -434,7 +434,7 @@
      * stream returned by mapper
      * @return a collector which applies the mapping function to the input
      * elements and provides the flat mapped results to the downstream collector
-     * @since 1.9
+     * @since 9
      */
     public static <T, U, A, R>
     Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
@@ -452,6 +452,53 @@
     }
 
     /**
+     * Adapts a {@code Collector} to one accepting elements of the same type
+     * {@code T} by applying the predicate to each input element and only
+     * accumulating if the predicate returns {@code true}.
+     *
+     * @apiNote
+     * The {@code filtering()} collectors are most useful when used in a
+     * multi-level reduction, such as downstream of a {@code groupingBy} or
+     * {@code partitioningBy}.  For example, given a stream of
+     * {@code Employee}, to accumulate the employees in each department that have a
+     * salary above a certain threshold:
+     * <pre>{@code
+     *     Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
+     *         = employees.stream().collect(groupingBy(Employee::getDepartment,
+     *                                              filtering(e -> e.getSalary() > 2000, toSet())));
+     * }</pre>
+     * A filtering collector differs from a stream's {@code filter()} operation.
+     * In this example, suppose there are no employees whose salary is above the
+     * threshold in some department.  Using a filtering collector as shown above
+     * would result in a mapping from that department to an empty {@code Set}.
+     * If a stream {@code filter()} operation were done instead, there would be
+     * no mapping for that department at all.
+     *
+     * @param <T> the type of the input elements
+     * @param <A> intermediate accumulation type of the downstream collector
+     * @param <R> result type of collector
+     * @param predicate a predicate to be applied to the input elements
+     * @param downstream a collector which will accept values that match the
+     * predicate
+     * @return a collector which applies the predicate to the input elements
+     * and provides matching elements to the downstream collector
+     * @since 9
+     */
+    public static <T, A, R>
+    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
+                               Collector<? super T, A, R> downstream) {
+        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
+        return new CollectorImpl<>(downstream.supplier(),
+                                   (r, t) -> {
+                                       if (predicate.test(t)) {
+                                           downstreamAccumulator.accept(r, t);
+                                       }
+                                   },
+                                   downstream.combiner(), downstream.finisher(),
+                                   downstream.characteristics());
+    }
+
+    /**
      * Adapts a {@code Collector} to perform an additional finishing
      * transformation.  For example, one could adapt the {@link #toList()}
      * collector to always produce an immutable list with:
--- a/src/java.base/share/classes/java/util/zip/ZipCoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/zip/ZipCoder.java	Tue Dec 22 13:41:12 2015 -0800
@@ -43,7 +43,7 @@
 
 final class ZipCoder {
 
-    String toString(byte[] ba, int length) {
+    String toString(byte[] ba, int off, int length) {
         CharsetDecoder cd = decoder().reset();
         int len = (int)(length * cd.maxCharsPerByte());
         char[] ca = new char[len];
@@ -53,12 +53,12 @@
         // CodingErrorAction.REPLACE mode. ZipCoder uses
         // REPORT mode.
         if (isUTF8 && cd instanceof ArrayDecoder) {
-            int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca);
+            int clen = ((ArrayDecoder)cd).decode(ba, off, length, ca);
             if (clen == -1)    // malformed
                 throw new IllegalArgumentException("MALFORMED");
             return new String(ca, 0, clen);
         }
-        ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+        ByteBuffer bb = ByteBuffer.wrap(ba, off, length);
         CharBuffer cb = CharBuffer.wrap(ca);
         CoderResult cr = cd.decode(bb, cb, true);
         if (!cr.isUnderflow())
@@ -69,8 +69,12 @@
         return new String(ca, 0, cb.position());
     }
 
+    String toString(byte[] ba, int length) {
+        return toString(ba, 0, length);
+    }
+
     String toString(byte[] ba) {
-        return toString(ba, ba.length);
+        return toString(ba, 0, ba.length);
     }
 
     byte[] getBytes(String s) {
@@ -111,13 +115,16 @@
         return utf8.getBytes(s);
     }
 
+    String toStringUTF8(byte[] ba, int len) {
+        return toStringUTF8(ba, 0, len);
+    }
 
-    String toStringUTF8(byte[] ba, int len) {
+    String toStringUTF8(byte[] ba, int off, int len) {
         if (isUTF8)
-            return toString(ba, len);
+            return toString(ba, off, len);
         if (utf8 == null)
             utf8 = new ZipCoder(StandardCharsets.UTF_8);
-        return utf8.toString(ba, len);
+        return utf8.toString(ba, off, len);
     }
 
     boolean isUTF8() {
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java	Tue Dec 22 13:41:12 2015 -0800
@@ -30,14 +30,22 @@
 import java.io.IOException;
 import java.io.EOFException;
 import java.io.File;
+import java.io.RandomAccessFile;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.Path;
+import java.nio.file.Files;
+
 import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Deque;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Objects;
 import java.util.NoSuchElementException;
 import java.util.Spliterator;
 import java.util.Spliterators;
@@ -47,7 +55,9 @@
 import jdk.internal.misc.JavaUtilZipFileAccess;
 import jdk.internal.misc.SharedSecrets;
 
+import static java.util.zip.ZipConstants.*;
 import static java.util.zip.ZipConstants64.*;
+import static java.util.zip.ZipUtils.*;
 
 /**
  * This class is used to read entries from a zip file.
@@ -60,11 +70,11 @@
  */
 public
 class ZipFile implements ZipConstants, Closeable {
-    private long jzfile;  // address of jzfile data
+
     private final String name;     // zip file name
-    private final int total;       // total number of entries
-    private final boolean locsig;  // if zip file starts with LOCSIG (usually true)
     private volatile boolean closeRequested = false;
+    private Source zsrc;
+    private ZipCoder zc;
 
     private static final int STORED = ZipEntry.STORED;
     private static final int DEFLATED = ZipEntry.DEFLATED;
@@ -83,23 +93,6 @@
      */
     public static final int OPEN_DELETE = 0x4;
 
-    static {
-        /* Zip library is loaded from System.initializeSystemClass */
-        initIDs();
-    }
-
-    private static native void initIDs();
-
-    private static final boolean usemmap;
-
-    static {
-        // A system prpperty to disable mmap use to avoid vm crash when
-        // in-use zip file is accidently overwritten by others.
-        String prop = sun.misc.VM.getSavedProperty("sun.zip.disableMemoryMapping");
-        usemmap = (prop == null ||
-                   !(prop.length() == 0 || prop.equalsIgnoreCase("true")));
-    }
-
     /**
      * Opens a zip file for reading.
      *
@@ -165,8 +158,6 @@
         this(file, OPEN_READ);
     }
 
-    private ZipCoder zc;
-
     /**
      * Opens a new {@code ZipFile} to read from the specified
      * {@code File} object in the specified mode.  The mode argument
@@ -214,16 +205,13 @@
                 sm.checkDelete(name);
             }
         }
-        if (charset == null)
-            throw new NullPointerException("charset is null");
+        Objects.requireNonNull(charset, "charset");
         this.zc = ZipCoder.get(charset);
+        this.name = name;
         long t0 = System.nanoTime();
-        jzfile = open(name, mode, file.lastModified(), usemmap);
+        this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
         sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
         sun.misc.PerfCounter.getZipFileCount().increment();
-        this.name = name;
-        this.total = getTotal(jzfile);
-        this.locsig = startsWithLOC(jzfile);
     }
 
     /**
@@ -257,6 +245,7 @@
 
     /**
      * Opens a ZIP file for reading given the specified File object.
+     *
      * @param file the ZIP file to be opened for reading
      * @param charset
      *        The {@linkplain java.nio.charset.Charset charset} to be
@@ -287,10 +276,10 @@
     public String getComment() {
         synchronized (this) {
             ensureOpen();
-            byte[] bcomm = getCommentBytes(jzfile);
-            if (bcomm == null)
+            if (zsrc.comment == null) {
                 return null;
-            return zc.toString(bcomm, bcomm.length);
+            }
+            return zc.toString(zsrc.comment);
         }
     }
 
@@ -303,38 +292,28 @@
      * @throws IllegalStateException if the zip file has been closed
      */
     public ZipEntry getEntry(String name) {
-        if (name == null) {
-            throw new NullPointerException("name");
-        }
-        long jzentry = 0;
+
+        Objects.requireNonNull(name, "name");
         synchronized (this) {
             ensureOpen();
-            jzentry = getEntry(jzfile, zc.getBytes(name), true);
-            if (jzentry != 0) {
-                ZipEntry ze = getZipEntry(name, jzentry);
-                freeEntry(jzfile, jzentry);
-                return ze;
+            int pos = zsrc.getEntryPos(zc.getBytes(name), true);
+            if (pos != -1) {
+                return getZipEntry(name, pos);
             }
         }
         return null;
     }
 
-    private static native long getEntry(long jzfile, byte[] name,
-                                        boolean addSlash);
-
-    // freeEntry releases the C jzentry struct.
-    private static native void freeEntry(long jzfile, long jzentry);
-
-    // the outstanding inputstreams that need to be closed,
+    // The outstanding inputstreams that need to be closed,
     // mapped to the inflater objects they use.
     private final Map<InputStream, Inflater> streams = new WeakHashMap<>();
 
     /**
      * Returns an input stream for reading the contents of the specified
      * zip file entry.
-     *
-     * <p> Closing this ZIP file will, in turn, close all input
-     * streams that have been returned by invocations of this method.
+     * <p>
+     * Closing this ZIP file will, in turn, close all input streams that
+     * have been returned by invocations of this method.
      *
      * @param entry the zip file entry
      * @return the input stream for reading the contents of the specified
@@ -344,37 +323,38 @@
      * @throws IllegalStateException if the zip file has been closed
      */
     public InputStream getInputStream(ZipEntry entry) throws IOException {
-        if (entry == null) {
-            throw new NullPointerException("entry");
-        }
-        long jzentry = 0;
+        Objects.requireNonNull(entry, "entry");
+        int pos = -1;
         ZipFileInputStream in = null;
         synchronized (this) {
             ensureOpen();
             if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
-                jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
+                pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false);
             } else {
-                jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
+                pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
             }
-            if (jzentry == 0) {
+            if (pos == -1) {
                 return null;
             }
-            in = new ZipFileInputStream(jzentry);
-
-            switch (getEntryMethod(jzentry)) {
+            in = new ZipFileInputStream(zsrc.cen, pos);
+            switch (CENHOW(zsrc.cen, pos)) {
             case STORED:
                 synchronized (streams) {
                     streams.put(in, null);
                 }
                 return in;
             case DEFLATED:
+                // Inflater likes a bit of slack
                 // MORE: Compute good size for inflater stream:
-                long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
-                if (size > 65536) size = 8192;
-                if (size <= 0) size = 4096;
+                long size = CENLEN(zsrc.cen, pos) + 2;
+                if (size > 65536) {
+                    size = 8192;
+                }
+                if (size <= 0) {
+                    size = 4096;
+                }
                 Inflater inf = getInflater();
-                InputStream is =
-                    new ZipFileInflaterInputStream(in, inf, (int)size);
+                InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size);
                 synchronized (streams) {
                     streams.put(is, inf);
                 }
@@ -447,8 +427,8 @@
     private Inflater getInflater() {
         Inflater inf;
         synchronized (inflaterCache) {
-            while (null != (inf = inflaterCache.poll())) {
-                if (false == inf.ended()) {
+            while ((inf = inflaterCache.poll()) != null) {
+                if (!inf.ended()) {
                     return inf;
                 }
             }
@@ -460,7 +440,7 @@
      * Releases the specified inflater to the list of available inflaters.
      */
     private void releaseInflater(Inflater inf) {
-        if (false == inf.ended()) {
+        if (!inf.ended()) {
             inf.reset();
             synchronized (inflaterCache) {
                 inflaterCache.add(inf);
@@ -469,7 +449,7 @@
     }
 
     // List of available Inflater objects for decompression
-    private Deque<Inflater> inflaterCache = new ArrayDeque<>();
+    private final Deque<Inflater> inflaterCache = new ArrayDeque<>();
 
     /**
      * Returns the path name of the ZIP file.
@@ -493,7 +473,7 @@
         public boolean hasNext() {
             synchronized (ZipFile.this) {
                 ensureOpen();
-                return i < total;
+                return i < zsrc.total;
             }
         }
 
@@ -504,28 +484,11 @@
         public ZipEntry next() {
             synchronized (ZipFile.this) {
                 ensureOpen();
-                if (i >= total) {
+                if (i >= zsrc.total) {
                     throw new NoSuchElementException();
                 }
-                long jzentry = getNextEntry(jzfile, i++);
-                if (jzentry == 0) {
-                    String message;
-                    if (closeRequested) {
-                        message = "ZipFile concurrently closed";
-                    } else {
-                        message = getZipMessage(ZipFile.this.jzfile);
-                    }
-                    throw new ZipError("jzentry == 0" +
-                                       ",\n jzfile = " + ZipFile.this.jzfile +
-                                       ",\n total = " + ZipFile.this.total +
-                                       ",\n name = " + ZipFile.this.name +
-                                       ",\n i = " + i +
-                                       ",\n message = " + message
-                        );
-                }
-                ZipEntry ze = getZipEntry(null, jzentry);
-                freeEntry(jzfile, jzentry);
-                return ze;
+                // each "entry" has 3 ints in table entries
+                return getZipEntry(null, zsrc.getEntryPos(i++ * 3));
             }
         }
 
@@ -559,48 +522,53 @@
                         Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
     }
 
-    private ZipEntry getZipEntry(String name, long jzentry) {
+    /* Checks ensureOpen() before invoke this method */
+    private ZipEntry getZipEntry(String name, int pos) {
+        byte[] cen = zsrc.cen;
         ZipEntry e = new ZipEntry();
-        e.flag = getEntryFlag(jzentry);  // get the flag first
+        int nlen = CENNAM(cen, pos);
+        int elen = CENEXT(cen, pos);
+        int clen = CENCOM(cen, pos);
+        e.flag = CENFLG(cen, pos);  // get the flag first
         if (name != null) {
             e.name = name;
         } else {
-            byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
             if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.name = zc.toStringUTF8(bname, bname.length);
+                e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
             } else {
-                e.name = zc.toString(bname, bname.length);
+                e.name = zc.toString(cen, pos + CENHDR, nlen);
             }
         }
-        e.xdostime = getEntryTime(jzentry);
-        e.crc = getEntryCrc(jzentry);
-        e.size = getEntrySize(jzentry);
-        e.csize = getEntryCSize(jzentry);
-        e.method = getEntryMethod(jzentry);
-        e.setExtra0(getEntryBytes(jzentry, JZENTRY_EXTRA), false);
-        byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
-        if (bcomm == null) {
-            e.comment = null;
-        } else {
+        e.xdostime = CENTIM(cen, pos);
+        e.crc = CENCRC(cen, pos);
+        e.size = CENLEN(cen, pos);
+        e.csize = CENSIZ(cen, pos);
+        e.method = CENHOW(cen, pos);
+        if (elen != 0) {
+            e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen,
+                                           pos + CENHDR + nlen + elen), true);
+        }
+        if (clen != 0) {
             if (!zc.isUTF8() && (e.flag & EFS) != 0) {
-                e.comment = zc.toStringUTF8(bcomm, bcomm.length);
+                e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen);
             } else {
-                e.comment = zc.toString(bcomm, bcomm.length);
+                e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen);
             }
         }
         return e;
     }
 
-    private static native long getNextEntry(long jzfile, int i);
-
     /**
      * Returns the number of entries in the ZIP file.
+     *
      * @return the number of entries in the ZIP file
      * @throws IllegalStateException if the zip file has been closed
      */
     public int size() {
-        ensureOpen();
-        return total;
+        synchronized (this) {
+            ensureOpen();
+            return zsrc.total;
+        }
     }
 
     /**
@@ -612,14 +580,15 @@
      * @throws IOException if an I/O error has occurred
      */
     public void close() throws IOException {
-        if (closeRequested)
+        if (closeRequested) {
             return;
+        }
         closeRequested = true;
 
         synchronized (this) {
             // Close streams, release their inflaters
             synchronized (streams) {
-                if (false == streams.isEmpty()) {
+                if (!streams.isEmpty()) {
                     Map<InputStream, Inflater> copy = new HashMap<>(streams);
                     streams.clear();
                     for (Map.Entry<InputStream, Inflater> e : copy.entrySet()) {
@@ -631,21 +600,17 @@
                     }
                 }
             }
-
             // Release cached inflaters
-            Inflater inf;
             synchronized (inflaterCache) {
-                while (null != (inf = inflaterCache.poll())) {
+                Inflater inf;
+                while ((inf = inflaterCache.poll()) != null) {
                     inf.end();
                 }
             }
-
-            if (jzfile != 0) {
-                // Close the zip file
-                long zf = this.jzfile;
-                jzfile = 0;
-
-                close(zf);
+            // Release zip src
+            if (zsrc != null) {
+                Source.close(zsrc);
+                zsrc = null;
             }
         }
     }
@@ -668,14 +633,11 @@
         close();
     }
 
-    private static native void close(long jzfile);
-
     private void ensureOpen() {
         if (closeRequested) {
             throw new IllegalStateException("zip file closed");
         }
-
-        if (jzfile == 0) {
+        if (zsrc == null) {
             throw new IllegalStateException("The object is not initialized.");
         }
     }
@@ -691,40 +653,99 @@
      * (possibly compressed) zip file entry.
      */
    private class ZipFileInputStream extends InputStream {
-        private volatile boolean zfisCloseRequested = false;
-        protected long jzentry; // address of jzentry data
+        private volatile boolean closeRequested = false;
         private   long pos;     // current position within entry data
         protected long rem;     // number of remaining bytes within entry
         protected long size;    // uncompressed size of this entry
 
-        ZipFileInputStream(long jzentry) {
-            pos = 0;
-            rem = getEntryCSize(jzentry);
-            size = getEntrySize(jzentry);
-            this.jzentry = jzentry;
+        ZipFileInputStream(byte[] cen, int cenpos) throws IOException {
+            rem = CENSIZ(cen, cenpos);
+            size = CENLEN(cen, cenpos);
+            pos = CENOFF(cen, cenpos);
+            // zip64
+            if (rem == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL ||
+                pos == ZIP64_MAGICVAL) {
+                checkZIP64(cen, cenpos);
+            }
+            // negative for lazy initialization, see getDataOffset();
+            pos = - (pos + ZipFile.this.zsrc.locpos);
+        }
+
+        private void checkZIP64(byte[] cen, int cenpos) throws IOException {
+            int off = cenpos + CENHDR + CENNAM(cen, cenpos);
+            int end = off + CENEXT(cen, cenpos);
+            while (off + 4 < end) {
+                int tag = get16(cen, off);
+                int sz = get16(cen, off + 2);
+                off += 4;
+                if (off + sz > end)         // invalid data
+                    break;
+                if (tag == EXTID_ZIP64) {
+                    if (size == ZIP64_MAGICVAL) {
+                        if (sz < 8 || (off + 8) > end)
+                            break;
+                        size = get64(cen, off);
+                        sz -= 8;
+                        off += 8;
+                    }
+                    if (rem == ZIP64_MAGICVAL) {
+                        if (sz < 8 || (off + 8) > end)
+                            break;
+                        rem = get64(cen, off);
+                        sz -= 8;
+                        off += 8;
+                    }
+                    if (pos == ZIP64_MAGICVAL) {
+                        if (sz < 8 || (off + 8) > end)
+                            break;
+                        pos = get64(cen, off);
+                        sz -= 8;
+                        off += 8;
+                    }
+                    break;
+                }
+                off += sz;
+            }
+        }
+
+       /* The Zip file spec explicitly allows the LOC extra data size to
+        * be different from the CEN extra data size. Since we cannot trust
+        * the CEN extra data size, we need to read the LOC to determine
+        * the entry data offset.
+        */
+        private long initDataOffset() throws IOException {
+            if (pos <= 0) {
+                byte[] loc = new byte[LOCHDR];
+                pos = -pos;
+                int len = ZipFile.this.zsrc.readFullyAt(loc, 0, loc.length, pos);
+                if (len != LOCHDR) {
+                    throw new ZipException("ZipFile error reading zip file");
+                }
+                if (LOCSIG(loc) != LOCSIG) {
+                    throw new ZipException("ZipFile invalid LOC header (bad signature)");
+                }
+                pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc);
+            }
+            return pos;
         }
 
         public int read(byte b[], int off, int len) throws IOException {
             synchronized (ZipFile.this) {
-                long rem = this.rem;
-                long pos = this.pos;
+                ensureOpenOrZipException();
+                initDataOffset();
                 if (rem == 0) {
                     return -1;
                 }
+                if (len > rem) {
+                    len = (int) rem;
+                }
                 if (len <= 0) {
                     return 0;
                 }
-                if (len > rem) {
-                    len = (int) rem;
-                }
-
-                // Check if ZipFile open
-                ensureOpenOrZipException();
-                len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b,
-                                   off, len);
+                len = ZipFile.this.zsrc.readAt(b, off, len, pos);
                 if (len > 0) {
-                    this.pos = (pos + len);
-                    this.rem = (rem - len);
+                    pos += len;
+                    rem -= len;
                 }
             }
             if (rem == 0) {
@@ -742,11 +763,16 @@
             }
         }
 
-        public long skip(long n) {
-            if (n > rem)
-                n = rem;
-            pos += n;
-            rem -= n;
+        public long skip(long n) throws IOException {
+            synchronized (ZipFile.this) {
+                ensureOpenOrZipException();
+                initDataOffset();
+                if (n > rem) {
+                    n = rem;
+                }
+                pos += n;
+                rem -= n;
+            }
             if (rem == 0) {
                 close();
             }
@@ -762,17 +788,11 @@
         }
 
         public void close() {
-            if (zfisCloseRequested)
+            if (closeRequested) {
                 return;
-            zfisCloseRequested = true;
-
+            }
+            closeRequested = true;
             rem = 0;
-            synchronized (ZipFile.this) {
-                if (jzentry != 0 && ZipFile.this.jzfile != 0) {
-                    freeEntry(ZipFile.this.jzfile, jzentry);
-                    jzentry = 0;
-                }
-            }
             synchronized (streams) {
                 streams.remove(this);
             }
@@ -787,40 +807,502 @@
         SharedSecrets.setJavaUtilZipFileAccess(
             new JavaUtilZipFileAccess() {
                 public boolean startsWithLocHeader(ZipFile zip) {
-                    return zip.startsWithLocHeader();
+                    return zip.zsrc.startsWithLoc;
                 }
-            }
+                public String[] getMetaInfEntryNames(ZipFile zip) {
+                    return zip.getMetaInfEntryNames();
+                }
+             }
         );
     }
 
-    /**
-     * Returns {@code true} if, and only if, the zip file begins with {@code
-     * LOCSIG}.
+    /*
+     * Returns an array of strings representing the names of all entries
+     * that begin with "META-INF/" (case ignored). This method is used
+     * in JarFile, via SharedSecrets, as an optimization when looking up
+     * manifest and signature file entries. Returns null if no entries
+     * were found.
      */
-    private boolean startsWithLocHeader() {
-        return locsig;
+    private String[] getMetaInfEntryNames() {
+        synchronized (this) {
+            ensureOpen();
+            if (zsrc.metanames.size() == 0) {
+                return null;
+            }
+            String[] names = new String[zsrc.metanames.size()];
+            byte[] cen = zsrc.cen;
+            for (int i = 0; i < names.length; i++) {
+                int pos = zsrc.metanames.get(i);
+                names[i] = new String(cen, pos + CENHDR,  CENNAM(cen, pos),
+                                      StandardCharsets.UTF_8);
+            }
+            return names;
+        }
     }
 
-    private static native long open(String name, int mode, long lastModified,
-                                    boolean usemmap) throws IOException;
-    private static native int getTotal(long jzfile);
-    private static native boolean startsWithLOC(long jzfile);
-    private static native int read(long jzfile, long jzentry,
-                                   long pos, byte[] b, int off, int len);
+    private static class Source {
+        private final Key key;               // the key in files
+        private int refs = 1;
 
-    // access to the native zentry object
-    private static native long getEntryTime(long jzentry);
-    private static native long getEntryCrc(long jzentry);
-    private static native long getEntryCSize(long jzentry);
-    private static native long getEntrySize(long jzentry);
-    private static native int getEntryMethod(long jzentry);
-    private static native int getEntryFlag(long jzentry);
-    private static native byte[] getCommentBytes(long jzfile);
+        private RandomAccessFile zfile;      // zfile of the underlying zip file
+        private byte[] cen;                  // CEN & ENDHDR
+        private long locpos;                 // position of first LOC header (usually 0)
+        private byte[] comment;              // zip file comment
+                                             // list of meta entries in META-INF dir
+        private ArrayList<Integer> metanames = new ArrayList<>();
+        private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true)
 
-    private static final int JZENTRY_NAME = 0;
-    private static final int JZENTRY_EXTRA = 1;
-    private static final int JZENTRY_COMMENT = 2;
-    private static native byte[] getEntryBytes(long jzentry, int type);
+        // A Hashmap for all entries.
+        //
+        // A cen entry of Zip/JAR file. As we have one for every entry in every active Zip/JAR,
+        // We might have a lot of these in a typical system. In order to save space we don't
+        // keep the name in memory, but merely remember a 32 bit {@code hash} value of the
+        // entry name and its offset {@code pos} in the central directory hdeader.
+        //
+        // private static class Entry {
+        //     int hash;       // 32 bit hashcode on name
+        //     int next;       // hash chain: index into entries
+        //     int pos;        // Offset of central directory file header
+        // }
+        // private Entry[] entries;             // array of hashed cen entry
+        //
+        // To reduce the total size of entries further, we use a int[] here to store 3 "int"
+        // {@code hash}, {@code next and {@code "pos for each entry. The entry can then be
+        // referred by their index of their positions in the {@code entries}.
+        //
+        private int[] entries;                  // array of hashed cen entry
+        private int addEntry(int index, int hash, int next, int pos) {
+            entries[index++] = hash;
+            entries[index++] = next;
+            entries[index++] = pos;
+            return index;
+        }
+        private int getEntryHash(int index) { return entries[index]; }
+        private int getEntryNext(int index) { return entries[index + 1]; }
+        private int getEntryPos(int index)  { return entries[index + 2]; }
+        private static final int ZIP_ENDCHAIN  = -1;
+        private int total;                   // total number of entries
+        private int[] table;                 // Hash chain heads: indexes into entries
+        private int tablelen;                // number of hash heads
 
-    private static native String getZipMessage(long jzfile);
+        private static class Key {
+            BasicFileAttributes attrs;
+            File file;
+
+            public Key(File file, BasicFileAttributes attrs) {
+                this.attrs = attrs;
+                this.file = file;
+            }
+
+            public int hashCode() {
+                long t = attrs.lastModifiedTime().toMillis();
+                return ((int)(t ^ (t >>> 32))) + file.hashCode();
+            }
+
+            public boolean equals(Object obj) {
+                if (obj instanceof Key) {
+                    Key key = (Key)obj;
+                    if (!attrs.lastModifiedTime().equals(key.attrs.lastModifiedTime())) {
+                        return false;
+                    }
+                    Object fk = attrs.fileKey();
+                    if (fk != null) {
+                        return  fk.equals(key.attrs.fileKey());
+                    } else {
+                        return file.equals(key.file);
+                    }
+                }
+                return false;
+            }
+        }
+        private static final HashMap<Key, Source> files = new HashMap<>();
+
+
+        public static Source get(File file, boolean toDelete) throws IOException {
+            Key key = new Key(file,
+                              Files.readAttributes(file.toPath(), BasicFileAttributes.class));
+            Source src = null;
+            synchronized (files) {
+                src = files.get(key);
+                if (src != null) {
+                    src.refs++;
+                    return src;
+                }
+            }
+            src = new Source(key, toDelete);
+
+            synchronized (files) {
+                if (files.containsKey(key)) {    // someone else put in first
+                    src.close();                 // close the newly created one
+                    src = files.get(key);
+                    src.refs++;
+                    return src;
+                }
+                files.put(key, src);
+                return src;
+            }
+        }
+
+        private static void close(Source src) throws IOException {
+            synchronized (files) {
+                if (--src.refs == 0) {
+                    files.remove(src.key);
+                    src.close();
+                }
+            }
+        }
+
+        private Source(Key key, boolean toDelete) throws IOException {
+            this.key = key;
+            this.zfile = new RandomAccessFile(key.file, "r");
+            if (toDelete) {
+                key.file.delete();
+            }
+            try {
+                initCEN(-1);
+                byte[] buf = new byte[4];
+                readFullyAt(buf, 0, 4, 0);
+                this.startsWithLoc = (LOCSIG(buf) == LOCSIG);
+            } catch (IOException x) {
+                try {
+                    this.zfile.close();
+                } catch (IOException xx) {}
+                throw x;
+            }
+        }
+
+        private void close() throws IOException {
+            zfile.close();
+            zfile = null;
+            cen = null;
+            entries = null;
+            table = null;
+            metanames = null;
+        }
+
+        private static final int BUF_SIZE = 8192;
+        private final int readFullyAt(byte[] buf, int off, int len, long pos)
+            throws IOException
+        {
+            synchronized(zfile) {
+                zfile.seek(pos);
+                int N = len;
+                while (N > 0) {
+                    int n = Math.min(BUF_SIZE, N);
+                    zfile.readFully(buf, off, n);
+                    off += n;
+                    N -= n;
+                }
+                return len;
+            }
+        }
+
+        private final int readAt(byte[] buf, int off, int len, long pos)
+            throws IOException
+        {
+            synchronized(zfile) {
+                zfile.seek(pos);
+                return zfile.read(buf, off, len);
+            }
+        }
+
+        private static final int hashN(byte[] a, int off, int len) {
+            int h = 1;
+            while (len-- > 0) {
+                h = 31 * h + a[off++];
+            }
+            return h;
+        }
+
+        private static final int hash_append(int hash, byte b) {
+            return hash * 31 + b;
+        }
+
+        private static class End {
+            int  centot;     // 4 bytes
+            long cenlen;     // 4 bytes
+            long cenoff;     // 4 bytes
+            long endpos;     // 4 bytes
+        }
+
+        /*
+         * Searches for end of central directory (END) header. The contents of
+         * the END header will be read and placed in endbuf. Returns the file
+         * position of the END header, otherwise returns -1 if the END header
+         * was not found or an error occurred.
+         */
+        private End findEND() throws IOException {
+            long ziplen = zfile.length();
+            if (ziplen <= 0)
+                zerror("zip file is empty");
+            End end = new End();
+            byte[] buf = new byte[READBLOCKSZ];
+            long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
+            long minPos = minHDR - (buf.length - ENDHDR);
+            for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR)) {
+                int off = 0;
+                if (pos < 0) {
+                    // Pretend there are some NUL bytes before start of file
+                    off = (int)-pos;
+                    Arrays.fill(buf, 0, off, (byte)0);
+                }
+                int len = buf.length - off;
+                if (readFullyAt(buf, off, len, pos + off) != len ) {
+                    zerror("zip END header not found");
+                }
+                // Now scan the block backwards for END header signature
+                for (int i = buf.length - ENDHDR; i >= 0; i--) {
+                    if (buf[i+0] == (byte)'P'    &&
+                        buf[i+1] == (byte)'K'    &&
+                        buf[i+2] == (byte)'\005' &&
+                        buf[i+3] == (byte)'\006') {
+                        // Found ENDSIG header
+                        byte[] endbuf = Arrays.copyOfRange(buf, i, i + ENDHDR);
+                        end.centot = ENDTOT(endbuf);
+                        end.cenlen = ENDSIZ(endbuf);
+                        end.cenoff = ENDOFF(endbuf);
+                        end.endpos = pos + i;
+                        int comlen = ENDCOM(endbuf);
+                        if (end.endpos + ENDHDR + comlen != ziplen) {
+                            // ENDSIG matched, however the size of file comment in it does
+                            // not match the real size. One "common" cause for this problem
+                            // is some "extra" bytes are padded at the end of the zipfile.
+                            // Let's do some extra verification, we don't care about the
+                            // performance in this situation.
+                            byte[] sbuf = new byte[4];
+                            long cenpos = end.endpos - end.cenlen;
+                            long locpos = cenpos - end.cenoff;
+                            if  (cenpos < 0 ||
+                                 locpos < 0 ||
+                                 readFullyAt(sbuf, 0, sbuf.length, cenpos) != 4 ||
+                                 GETSIG(sbuf) != CENSIG ||
+                                 readFullyAt(sbuf, 0, sbuf.length, locpos) != 4 ||
+                                 GETSIG(sbuf) != LOCSIG) {
+                                continue;
+                            }
+                        }
+                        if (comlen > 0) {    // this zip file has comlen
+                            comment = new byte[comlen];
+                            if (readFullyAt(comment, 0, comlen, end.endpos + ENDHDR) != comlen) {
+                                zerror("zip comment read failed");
+                            }
+                        }
+                        if (end.cenlen == ZIP64_MAGICVAL ||
+                            end.cenoff == ZIP64_MAGICVAL ||
+                            end.centot == ZIP64_MAGICCOUNT)
+                        {
+                            // need to find the zip64 end;
+                            try {
+                                byte[] loc64 = new byte[ZIP64_LOCHDR];
+                                if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
+                                    != loc64.length || GETSIG(loc64) != ZIP64_LOCSIG) {
+                                    return end;
+                                }
+                                long end64pos = ZIP64_LOCOFF(loc64);
+                                byte[] end64buf = new byte[ZIP64_ENDHDR];
+                                if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
+                                    != end64buf.length || GETSIG(end64buf) != ZIP64_ENDSIG) {
+                                    return end;
+                                }
+                                // end64 found, re-calcualte everything.
+                                end.cenlen = ZIP64_ENDSIZ(end64buf);
+                                end.cenoff = ZIP64_ENDOFF(end64buf);
+                                end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
+                                end.endpos = end64pos;
+                            } catch (IOException x) {}    // no zip64 loc/end
+                        }
+                        return end;
+                    }
+                }
+            }
+            zerror("zip END header not found");
+            return null; //make compiler happy
+        }
+
+        // Reads zip file central directory.
+        private void initCEN(int knownTotal) throws IOException {
+            if (knownTotal == -1) {
+                End end = findEND();
+                if (end.endpos == 0) {
+                    locpos = 0;
+                    total = 0;
+                    entries  = new int[0];
+                    cen = null;
+                    return;         // only END header present
+                }
+                if (end.cenlen > end.endpos)
+                    zerror("invalid END header (bad central directory size)");
+                long cenpos = end.endpos - end.cenlen;     // position of CEN table
+                // Get position of first local file (LOC) header, taking into
+                // account that there may be a stub prefixed to the zip file.
+                locpos = cenpos - end.cenoff;
+                if (locpos < 0) {
+                    zerror("invalid END header (bad central directory offset)");
+                }
+                // read in the CEN and END
+                cen = new byte[(int)(end.cenlen + ENDHDR)];
+                if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
+                    zerror("read CEN tables failed");
+                }
+                total = end.centot;
+            } else {
+                total = knownTotal;
+            }
+            // hash table for entries
+            entries  = new int[total * 3];
+            tablelen = ((total/2) | 1); // Odd -> fewer collisions
+            table    =  new int[tablelen];
+            Arrays.fill(table, ZIP_ENDCHAIN);
+            int idx = 0;
+            int hash = 0;
+            int next = -1;
+
+            // list for all meta entries
+            metanames = new ArrayList<>();
+
+            // Iterate through the entries in the central directory
+            int i = 0;
+            int hsh = 0;
+            int pos = 0;
+            int limit = cen.length - ENDHDR;
+            while (pos + CENHDR  <= limit) {
+                if (i >= total) {
+                    // This will only happen if the zip file has an incorrect
+                    // ENDTOT field, which usually means it contains more than
+                    // 65535 entries.
+                    initCEN(countCENHeaders(cen, limit));
+                    return;
+                }
+                if (CENSIG(cen, pos) != CENSIG)
+                    zerror("invalid CEN header (bad signature)");
+                int method = CENHOW(cen, pos);
+                int nlen   = CENNAM(cen, pos);
+                int elen   = CENEXT(cen, pos);
+                int clen   = CENCOM(cen, pos);
+                if ((CENFLG(cen, pos) & 1) != 0)
+                    zerror("invalid CEN header (encrypted entry)");
+                if (method != STORED && method != DEFLATED)
+                    zerror("invalid CEN header (bad compression method: " + method + ")");
+                if (pos + CENHDR + nlen > limit)
+                    zerror("invalid CEN header (bad header size)");
+                // Record the CEN offset and the name hash in our hash cell.
+                hash = hashN(cen, pos + CENHDR, nlen);
+                hsh = (hash & 0x7fffffff) % tablelen;
+                next = table[hsh];
+                table[hsh] = idx;
+                idx = addEntry(idx, hash, next, pos);
+                // Adds name to metanames.
+                if (isMetaName(cen, pos + CENHDR, nlen)) {
+                    metanames.add(pos);
+                }
+                // skip ext and comment
+                pos += (CENHDR + nlen + elen + clen);
+                i++;
+            }
+            total = i;
+            if (pos + ENDHDR != cen.length) {
+                zerror("invalid CEN header (bad header size)");
+            }
+        }
+
+        private static void zerror(String msg) throws ZipException {
+            throw new ZipException(msg);
+        }
+
+        /*
+         * Returns the {@code pos} of the zip cen entry corresponding to the
+         * specified entry name, or -1 if not found.
+         */
+        private int getEntryPos(byte[] name, boolean addSlash) {
+            if (total == 0) {
+                return -1;
+            }
+            int hsh = hashN(name, 0, name.length);
+            int idx = table[(hsh & 0x7fffffff) % tablelen];
+            /*
+             * This while loop is an optimization where a double lookup
+             * for name and name+/ is being performed. The name char
+             * array has enough room at the end to try again with a
+             * slash appended if the first table lookup does not succeed.
+             */
+            while(true) {
+                /*
+                 * Search down the target hash chain for a entry whose
+                 * 32 bit hash matches the hashed name.
+                 */
+                while (idx != ZIP_ENDCHAIN) {
+                    if (getEntryHash(idx) == hsh) {
+                        // The CEN name must match the specfied one
+                        int pos = getEntryPos(idx);
+                        if (name.length == CENNAM(cen, pos)) {
+                            boolean matched = true;
+                            int nameoff = pos + CENHDR;
+                            for (int i = 0; i < name.length; i++) {
+                                if (name[i] != cen[nameoff++]) {
+                                    matched = false;
+                                    break;
+                                }
+                            }
+                            if (matched) {
+                                return pos;
+                            }
+                         }
+                    }
+                    idx = getEntryNext(idx);
+                }
+                /* If not addSlash, or slash is already there, we are done */
+                if (!addSlash  || name[name.length - 1] == '/') {
+                     return -1;
+                }
+                /* Add slash and try once more */
+                name = Arrays.copyOf(name, name.length + 1);
+                name[name.length - 1] = '/';
+                hsh = hash_append(hsh, (byte)'/');
+                //idx = table[hsh % tablelen];
+                idx = table[(hsh & 0x7fffffff) % tablelen];
+                addSlash = false;
+            }
+        }
+
+        private static byte[] metainf = new byte[] {
+            'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/',
+        };
+
+        /*
+         * Returns true if the specified entry's name begins with the string
+         * "META-INF/" irrespective of case.
+         */
+        private static boolean isMetaName(byte[] name,  int off, int len) {
+            if (len < 9 || (name[off] != 'M' && name[off] != 'm')) {  //  sizeof("META-INF/") - 1
+                return false;
+            }
+            off++;
+            for (int i = 1; i < metainf.length; i++) {
+                byte c = name[off++];
+                // Avoid toupper; it's locale-dependent
+                if (c >= 'a' && c <= 'z') {
+                    c += 'A' - 'a';
+                }
+                if (metainf[i] != c) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /*
+         * Counts the number of CEN headers in a central directory extending
+         * from BEG to END.  Might return a bogus answer if the zip file is
+         * corrupt, but will not crash.
+         */
+        static int countCENHeaders(byte[] cen, int end) {
+            int count = 0;
+            int pos = 0;
+            while (pos + CENHDR <= end) {
+                count++;
+                pos += (CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos));
+            }
+            return count;
+        }
+    }
 }
--- a/src/java.base/share/classes/java/util/zip/ZipUtils.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java	Tue Dec 22 13:41:12 2015 -0800
@@ -31,6 +31,8 @@
 import java.time.ZoneId;
 import java.util.concurrent.TimeUnit;
 
+import static java.util.zip.ZipConstants.ENDHDR;
+
 class ZipUtils {
 
     // used to adjust values between Windows and java epoch
@@ -133,7 +135,7 @@
      * The bytes are assumed to be in Intel (little-endian) byte order.
      */
     public static final int get16(byte b[], int off) {
-        return Byte.toUnsignedInt(b[off]) | (Byte.toUnsignedInt(b[off+1]) << 8);
+        return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8);
     }
 
     /**
@@ -160,4 +162,79 @@
     public static final int get32S(byte b[], int off) {
         return (get16(b, off) | (get16(b, off+2) << 16));
     }
+
+    // fields access methods
+    static final int CH(byte[] b, int n) {
+        return b[n] & 0xff ;
+    }
+
+    static final int SH(byte[] b, int n) {
+        return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
+    }
+
+    static final long LG(byte[] b, int n) {
+        return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
+    }
+
+    static final long LL(byte[] b, int n) {
+        return (LG(b, n)) | (LG(b, n + 4) << 32);
+    }
+
+    static final long GETSIG(byte[] b) {
+        return LG(b, 0);
+    }
+
+    // local file (LOC) header fields
+    static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
+    static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
+    static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
+    static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
+    static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
+    static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
+    static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
+    static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
+    static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
+    static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
+
+    // extra local (EXT) header fields
+    static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
+    static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
+    static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
+
+    // end of central directory header (END) fields
+    static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
+    static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
+    static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
+    static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
+    static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
+    static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
+
+    // zip64 end of central directory recoder fields
+    static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
+    static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
+    static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
+    static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
+    static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
+
+    // central directory header (CEN) fields
+    static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
+    static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
+    static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
+    static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
+    static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
+    static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
+    static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
+    static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
+    static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
+    static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
+    static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
+    static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
+    static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
+    static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
+    static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
+    static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
+
+    // The END header is followed by a variable length comment of size < 64k.
+    static final long END_MAXLEN = 0xFFFF + ENDHDR;
+    static final int READBLOCKSZ = 128;
 }
--- a/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java	Tue Dec 22 13:41:12 2015 -0800
@@ -29,5 +29,6 @@
 
 public interface JavaUtilZipFileAccess {
     public boolean startsWithLocHeader(ZipFile zip);
+    public String[] getMetaInfEntryNames(ZipFile zip);
 }
 
--- a/src/java.base/share/classes/sun/misc/BASE64Decoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.OutputStream;
-import java.io.PushbackInputStream;
-import java.io.PrintStream;
-
-/**
- * This class implements a BASE64 Character decoder as specified in RFC1521.
- *
- * This RFC is part of the MIME specification which is published by the
- * Internet Engineering Task Force (IETF). Unlike some other encoding
- * schemes there is nothing in this encoding that tells the decoder
- * where a buffer starts or stops, so to use it you will need to isolate
- * your encoded data into a single chunk and then feed them this decoder.
- * The simplest way to do that is to read all of the encoded data into a
- * string and then use:
- * <pre>
- *      byte    mydata[];
- *      BASE64Decoder base64 = new BASE64Decoder();
- *
- *      mydata = base64.decodeBuffer(bufferString);
- * </pre>
- * This will decode the String in <i>bufferString</i> and give you an array
- * of bytes in the array <i>myData</i>.
- *
- * On errors, this class throws a CEFormatException with the following detail
- * strings:
- * <pre>
- *    "BASE64Decoder: Not enough bytes for an atom."
- * </pre>
- *
- * @author      Chuck McManis
- * @see         CharacterEncoder
- * @see         BASE64Decoder
- */
-
-public class BASE64Decoder extends CharacterDecoder {
-
-    /** This class has 4 bytes per atom */
-    protected int bytesPerAtom() {
-        return (4);
-    }
-
-    /** Any multiple of 4 will do, 72 might be common */
-    protected int bytesPerLine() {
-        return (72);
-    }
-
-    /**
-     * This character array provides the character to value map
-     * based on RFC1521.
-     */
-    private static final char pem_array[] = {
-        //       0   1   2   3   4   5   6   7
-                'A','B','C','D','E','F','G','H', // 0
-                'I','J','K','L','M','N','O','P', // 1
-                'Q','R','S','T','U','V','W','X', // 2
-                'Y','Z','a','b','c','d','e','f', // 3
-                'g','h','i','j','k','l','m','n', // 4
-                'o','p','q','r','s','t','u','v', // 5
-                'w','x','y','z','0','1','2','3', // 6
-                '4','5','6','7','8','9','+','/'  // 7
-        };
-
-    private static final byte pem_convert_array[] = new byte[256];
-
-    static {
-        for (int i = 0; i < 255; i++) {
-            pem_convert_array[i] = -1;
-        }
-        for (int i = 0; i < pem_array.length; i++) {
-            pem_convert_array[pem_array[i]] = (byte) i;
-        }
-    }
-
-    byte decode_buffer[] = new byte[4];
-
-    /**
-     * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
-     */
-    @SuppressWarnings("fallthrough")
-    protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem)
-        throws java.io.IOException
-    {
-        int     i;
-        byte    a = -1, b = -1, c = -1, d = -1;
-
-        if (rem < 2) {
-            throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
-        }
-        do {
-            i = inStream.read();
-            if (i == -1) {
-                throw new CEStreamExhausted();
-            }
-        } while (i == '\n' || i == '\r');
-        decode_buffer[0] = (byte) i;
-
-        i = readFully(inStream, decode_buffer, 1, rem-1);
-        if (i == -1) {
-            throw new CEStreamExhausted();
-        }
-
-        if (rem > 3 && decode_buffer[3] == '=') {
-            rem = 3;
-        }
-        if (rem > 2 && decode_buffer[2] == '=') {
-            rem = 2;
-        }
-        switch (rem) {
-        case 4:
-            d = pem_convert_array[decode_buffer[3] & 0xff];
-            // NOBREAK
-        case 3:
-            c = pem_convert_array[decode_buffer[2] & 0xff];
-            // NOBREAK
-        case 2:
-            b = pem_convert_array[decode_buffer[1] & 0xff];
-            a = pem_convert_array[decode_buffer[0] & 0xff];
-            break;
-        }
-
-        switch (rem) {
-        case 2:
-            outStream.write( (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
-            break;
-        case 3:
-            outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
-            outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
-            break;
-        case 4:
-            outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
-            outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
-            outStream.write( (byte) (((c << 6) & 0xc0) | (d  & 0x3f)) );
-            break;
-        }
-        return;
-    }
-}
--- a/src/java.base/share/classes/sun/misc/BASE64Encoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a BASE64 Character encoder as specified in RFC1521.
- * This RFC is part of the MIME specification as published by the Internet
- * Engineering Task Force (IETF). Unlike some other encoding schemes there
- * is nothing in this encoding that indicates
- * where a buffer starts or ends.
- *
- * This means that the encoded text will simply start with the first line
- * of encoded text and end with the last line of encoded text.
- *
- * @author      Chuck McManis
- * @see         CharacterEncoder
- * @see         BASE64Decoder
- */
-
-public class BASE64Encoder extends CharacterEncoder {
-
-    /** this class encodes three bytes per atom. */
-    protected int bytesPerAtom() {
-        return (3);
-    }
-
-    /**
-     * this class encodes 57 bytes per line. This results in a maximum
-     * of 57/3 * 4 or 76 characters per output line. Not counting the
-     * line termination.
-     */
-    protected int bytesPerLine() {
-        return (57);
-    }
-
-    /** This array maps the characters to their 6 bit values */
-    private static final char pem_array[] = {
-        //       0   1   2   3   4   5   6   7
-                'A','B','C','D','E','F','G','H', // 0
-                'I','J','K','L','M','N','O','P', // 1
-                'Q','R','S','T','U','V','W','X', // 2
-                'Y','Z','a','b','c','d','e','f', // 3
-                'g','h','i','j','k','l','m','n', // 4
-                'o','p','q','r','s','t','u','v', // 5
-                'w','x','y','z','0','1','2','3', // 6
-                '4','5','6','7','8','9','+','/'  // 7
-        };
-
-    /**
-     * encodeAtom - Take three bytes of input and encode it as 4
-     * printable characters. Note that if the length in len is less
-     * than three is encodes either one or two '=' signs to indicate
-     * padding characters.
-     */
-    protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len)
-        throws IOException {
-        byte a, b, c;
-
-        if (len == 1) {
-            a = data[offset];
-            b = 0;
-            c = 0;
-            outStream.write(pem_array[(a >>> 2) & 0x3F]);
-            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
-            outStream.write('=');
-            outStream.write('=');
-        } else if (len == 2) {
-            a = data[offset];
-            b = data[offset+1];
-            c = 0;
-            outStream.write(pem_array[(a >>> 2) & 0x3F]);
-            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
-            outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
-            outStream.write('=');
-        } else {
-            a = data[offset];
-            b = data[offset+1];
-            c = data[offset+2];
-            outStream.write(pem_array[(a >>> 2) & 0x3F]);
-            outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
-            outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
-            outStream.write(pem_array[c & 0x3F]);
-        }
-    }
-}
--- a/src/java.base/share/classes/sun/misc/CharacterDecoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class defines the decoding half of character encoders.
- * A character decoder is an algorithim for transforming 8 bit
- * binary data that has been encoded into text by a character
- * encoder, back into original binary form.
- *
- * The character encoders, in general, have been structured
- * around a central theme that binary data can be encoded into
- * text that has the form:
- *
- * <pre>
- *      [Buffer Prefix]
- *      [Line Prefix][encoded data atoms][Line Suffix]
- *      [Buffer Suffix]
- * </pre>
- *
- * Of course in the simplest encoding schemes, the buffer has no
- * distinct prefix of suffix, however all have some fixed relationship
- * between the text in an 'atom' and the binary data itself.
- *
- * In the CharacterEncoder and CharacterDecoder classes, one complete
- * chunk of data is referred to as a <i>buffer</i>. Encoded buffers
- * are all text, and decoded buffers (sometimes just referred to as
- * buffers) are binary octets.
- *
- * To create a custom decoder, you must, at a minimum,  overide three
- * abstract methods in this class.
- * <DL>
- * <DD>bytesPerAtom which tells the decoder how many bytes to
- * expect from decodeAtom
- * <DD>decodeAtom which decodes the bytes sent to it as text.
- * <DD>bytesPerLine which tells the encoder the maximum number of
- * bytes per line.
- * </DL>
- *
- * In general, the character decoders return error in the form of a
- * CEFormatException. The syntax of the detail string is
- * <pre>
- *      DecoderClassName: Error message.
- * </pre>
- *
- * Several useful decoders have already been written and are
- * referenced in the See Also list below.
- *
- * @author      Chuck McManis
- * @see         CEFormatException
- * @see         CharacterEncoder
- * @see         UCDecoder
- * @see         UUDecoder
- * @see         BASE64Decoder
- */
-
-public abstract class CharacterDecoder {
-
-    /** Return the number of bytes per atom of decoding */
-    protected abstract int bytesPerAtom();
-
-    /** Return the maximum number of bytes that can be encoded per line */
-    protected abstract int bytesPerLine();
-
-    /** decode the beginning of the buffer, by default this is a NOP. */
-    protected void decodeBufferPrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
-    /** decode the buffer suffix, again by default it is a NOP. */
-    protected void decodeBufferSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
-    /**
-     * This method should return, if it knows, the number of bytes
-     * that will be decoded. Many formats such as uuencoding provide
-     * this information. By default we return the maximum bytes that
-     * could have been encoded on the line.
-     */
-    protected int decodeLinePrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException {
-        return (bytesPerLine());
-    }
-
-    /**
-     * This method post processes the line, if there are error detection
-     * or correction codes in a line, they are generally processed by
-     * this method. The simplest version of this method looks for the
-     * (newline) character.
-     */
-    protected void decodeLineSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
-    /**
-     * This method does an actual decode. It takes the decoded bytes and
-     * writes them to the OutputStream. The integer <i>l</i> tells the
-     * method how many bytes are required. This is always {@literal <=} bytesPerAtom().
-     */
-    protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream, int l) throws IOException {
-        throw new CEStreamExhausted();
-    }
-
-    /**
-     * This method works around the bizarre semantics of BufferedInputStream's
-     * read method.
-     */
-    protected int readFully(InputStream in, byte buffer[], int offset, int len)
-        throws java.io.IOException {
-        for (int i = 0; i < len; i++) {
-            int q = in.read();
-            if (q == -1)
-                return ((i == 0) ? -1 : i);
-            buffer[i+offset] = (byte)q;
-        }
-        return len;
-    }
-
-    /**
-     * Decode the text from the InputStream and write the decoded
-     * octets to the OutputStream. This method runs until the stream
-     * is exhausted.
-     * @exception CEFormatException An error has occurred while decoding
-     * @exception CEStreamExhausted The input stream is unexpectedly out of data
-     */
-    public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException {
-        int     i;
-        int     totalBytes = 0;
-
-        PushbackInputStream ps = new PushbackInputStream (aStream);
-        decodeBufferPrefix(ps, bStream);
-        while (true) {
-            int length;
-
-            try {
-                length = decodeLinePrefix(ps, bStream);
-                for (i = 0; (i+bytesPerAtom()) < length; i += bytesPerAtom()) {
-                    decodeAtom(ps, bStream, bytesPerAtom());
-                    totalBytes += bytesPerAtom();
-                }
-                if ((i + bytesPerAtom()) == length) {
-                    decodeAtom(ps, bStream, bytesPerAtom());
-                    totalBytes += bytesPerAtom();
-                } else {
-                    decodeAtom(ps, bStream, length - i);
-                    totalBytes += (length - i);
-                }
-                decodeLineSuffix(ps, bStream);
-            } catch (CEStreamExhausted e) {
-                break;
-            }
-        }
-        decodeBufferSuffix(ps, bStream);
-    }
-
-    /**
-     * Alternate decode interface that takes a String containing the encoded
-     * buffer and returns a byte array containing the data.
-     * @exception CEFormatException An error has occurred while decoding
-     */
-    public byte[] decodeBuffer(String inputString) throws IOException {
-        byte inputBuffer[] = inputString.getBytes("ISO-8859-1");
-        ByteArrayInputStream inStream = new ByteArrayInputStream(inputBuffer);
-        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-        decodeBuffer(inStream, outStream);
-        return outStream.toByteArray();
-    }
-
-    /**
-     * Decode the contents of the inputstream into a buffer.
-     */
-    public byte[] decodeBuffer(InputStream in) throws IOException {
-        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-        decodeBuffer(in, outStream);
-        return outStream.toByteArray();
-    }
-
-    /**
-     * Decode the contents of the String into a ByteBuffer.
-     */
-    public ByteBuffer decodeBufferToByteBuffer(String inputString)
-        throws IOException {
-        return ByteBuffer.wrap(decodeBuffer(inputString));
-    }
-
-    /**
-     * Decode the contents of the inputStream into a ByteBuffer.
-     */
-    public ByteBuffer decodeBufferToByteBuffer(InputStream in)
-        throws IOException {
-        return ByteBuffer.wrap(decodeBuffer(in));
-    }
-}
--- a/src/java.base/share/classes/sun/misc/CharacterEncoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-
-/**
- * This class defines the encoding half of character encoders.
- * A character encoder is an algorithim for transforming 8 bit binary
- * data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text)
- * for transmition over text channels such as e-mail and network news.
- *
- * The character encoders have been structured around a central theme
- * that, in general, the encoded text has the form:
- *
- * <pre>
- *      [Buffer Prefix]
- *      [Line Prefix][encoded data atoms][Line Suffix]
- *      [Buffer Suffix]
- * </pre>
- *
- * In the CharacterEncoder and CharacterDecoder classes, one complete
- * chunk of data is referred to as a <i>buffer</i>. Encoded buffers
- * are all text, and decoded buffers (sometimes just referred to as
- * buffers) are binary octets.
- *
- * To create a custom encoder, you must, at a minimum,  overide three
- * abstract methods in this class.
- * <DL>
- * <DD>bytesPerAtom which tells the encoder how many bytes to
- * send to encodeAtom
- * <DD>encodeAtom which encodes the bytes sent to it as text.
- * <DD>bytesPerLine which tells the encoder the maximum number of
- * bytes per line.
- * </DL>
- *
- * Several useful encoders have already been written and are
- * referenced in the See Also list below.
- *
- * @author      Chuck McManis
- * @see         CharacterDecoder
- * @see         UCEncoder
- * @see         UUEncoder
- * @see         BASE64Encoder
- */
-public abstract class CharacterEncoder {
-
-    /** Stream that understands "printing" */
-    protected PrintStream pStream;
-
-    /** Return the number of bytes per atom of encoding */
-    protected abstract int bytesPerAtom();
-
-    /** Return the number of bytes that can be encoded per line */
-    protected abstract int bytesPerLine();
-
-    /**
-     * Encode the prefix for the entire buffer. By default is simply
-     * opens the PrintStream for use by the other functions.
-     */
-    protected void encodeBufferPrefix(OutputStream aStream) throws IOException {
-        pStream = new PrintStream(aStream);
-    }
-
-    /**
-     * Encode the suffix for the entire buffer.
-     */
-    protected void encodeBufferSuffix(OutputStream aStream) throws IOException {
-    }
-
-    /**
-     * Encode the prefix that starts every output line.
-     */
-    protected void encodeLinePrefix(OutputStream aStream, int aLength)
-    throws IOException {
-    }
-
-    /**
-     * Encode the suffix that ends every output line. By default
-     * this method just prints a newline into the output stream.
-     */
-    protected void encodeLineSuffix(OutputStream aStream) throws IOException {
-        pStream.println();
-    }
-
-    /** Encode one "atom" of information into characters. */
-    protected abstract void encodeAtom(OutputStream aStream, byte someBytes[],
-                int anOffset, int aLength) throws IOException;
-
-    /**
-     * This method works around the bizarre semantics of BufferedInputStream's
-     * read method.
-     */
-    protected int readFully(InputStream in, byte buffer[])
-        throws java.io.IOException {
-        for (int i = 0; i < buffer.length; i++) {
-            int q = in.read();
-            if (q == -1)
-                return i;
-            buffer[i] = (byte)q;
-        }
-        return buffer.length;
-    }
-
-    /**
-     * Encode bytes from the input stream, and write them as text characters
-     * to the output stream. This method will run until it exhausts the
-     * input stream, but does not print the line suffix for a final
-     * line that is shorter than bytesPerLine().
-     */
-    public void encode(InputStream inStream, OutputStream outStream)
-        throws IOException {
-        int     j;
-        int     numBytes;
-        byte    tmpbuffer[] = new byte[bytesPerLine()];
-
-        encodeBufferPrefix(outStream);
-
-        while (true) {
-            numBytes = readFully(inStream, tmpbuffer);
-            if (numBytes == 0) {
-                break;
-            }
-            encodeLinePrefix(outStream, numBytes);
-            for (j = 0; j < numBytes; j += bytesPerAtom()) {
-
-                if ((j + bytesPerAtom()) <= numBytes) {
-                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
-                } else {
-                    encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
-                }
-            }
-            if (numBytes < bytesPerLine()) {
-                break;
-            } else {
-                encodeLineSuffix(outStream);
-            }
-        }
-        encodeBufferSuffix(outStream);
-    }
-
-    /**
-     * Encode the buffer in <i>aBuffer</i> and write the encoded
-     * result to the OutputStream <i>aStream</i>.
-     */
-    public void encode(byte aBuffer[], OutputStream aStream)
-    throws IOException {
-        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
-        encode(inStream, aStream);
-    }
-
-    /**
-     * A 'streamless' version of encode that simply takes a buffer of
-     * bytes and returns a string containing the encoded buffer.
-     */
-    public String encode(byte aBuffer[]) {
-        ByteArrayOutputStream   outStream = new ByteArrayOutputStream();
-        ByteArrayInputStream    inStream = new ByteArrayInputStream(aBuffer);
-        String retVal = null;
-        try {
-            encode(inStream, outStream);
-            // explicit ascii->unicode conversion
-            retVal = outStream.toString("ISO-8859-1");
-        } catch (Exception IOException) {
-            // This should never happen.
-            throw new Error("CharacterEncoder.encode internal error");
-        }
-        return (retVal);
-    }
-
-    /**
-     * Return a byte array from the remaining bytes in this ByteBuffer.
-     * <P>
-     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
-     * <P>
-     * To avoid an extra copy, the implementation will attempt to return the
-     * byte array backing the ByteBuffer.  If this is not possible, a
-     * new byte array will be created.
-     */
-    private byte [] getBytes(ByteBuffer bb) {
-        /*
-         * This should never return a BufferOverflowException, as we're
-         * careful to allocate just the right amount.
-         */
-        byte [] buf = null;
-
-        /*
-         * If it has a usable backing byte buffer, use it.  Use only
-         * if the array exactly represents the current ByteBuffer.
-         */
-        if (bb.hasArray()) {
-            byte [] tmp = bb.array();
-            if ((tmp.length == bb.capacity()) &&
-                    (tmp.length == bb.remaining())) {
-                buf = tmp;
-                bb.position(bb.limit());
-            }
-        }
-
-        if (buf == null) {
-            /*
-             * This class doesn't have a concept of encode(buf, len, off),
-             * so if we have a partial buffer, we must reallocate
-             * space.
-             */
-            buf = new byte[bb.remaining()];
-
-            /*
-             * position() automatically updated
-             */
-            bb.get(buf);
-        }
-
-        return buf;
-    }
-
-    /**
-     * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
-     * result to the OutputStream <i>aStream</i>.
-     * <P>
-     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
-     */
-    public void encode(ByteBuffer aBuffer, OutputStream aStream)
-        throws IOException {
-        byte [] buf = getBytes(aBuffer);
-        encode(buf, aStream);
-    }
-
-    /**
-     * A 'streamless' version of encode that simply takes a ByteBuffer
-     * and returns a string containing the encoded buffer.
-     * <P>
-     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
-     */
-    public String encode(ByteBuffer aBuffer) {
-        byte [] buf = getBytes(aBuffer);
-        return encode(buf);
-    }
-
-    /**
-     * Encode bytes from the input stream, and write them as text characters
-     * to the output stream. This method will run until it exhausts the
-     * input stream. It differs from encode in that it will add the
-     * line at the end of a final line that is shorter than bytesPerLine().
-     */
-    public void encodeBuffer(InputStream inStream, OutputStream outStream)
-        throws IOException {
-        int     j;
-        int     numBytes;
-        byte    tmpbuffer[] = new byte[bytesPerLine()];
-
-        encodeBufferPrefix(outStream);
-
-        while (true) {
-            numBytes = readFully(inStream, tmpbuffer);
-            if (numBytes == 0) {
-                break;
-            }
-            encodeLinePrefix(outStream, numBytes);
-            for (j = 0; j < numBytes; j += bytesPerAtom()) {
-                if ((j + bytesPerAtom()) <= numBytes) {
-                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
-                } else {
-                    encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
-                }
-            }
-            encodeLineSuffix(outStream);
-            if (numBytes < bytesPerLine()) {
-                break;
-            }
-        }
-        encodeBufferSuffix(outStream);
-    }
-
-    /**
-     * Encode the buffer in <i>aBuffer</i> and write the encoded
-     * result to the OutputStream <i>aStream</i>.
-     */
-    public void encodeBuffer(byte aBuffer[], OutputStream aStream)
-    throws IOException {
-        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
-        encodeBuffer(inStream, aStream);
-    }
-
-    /**
-     * A 'streamless' version of encode that simply takes a buffer of
-     * bytes and returns a string containing the encoded buffer.
-     */
-    public String encodeBuffer(byte aBuffer[]) {
-        ByteArrayOutputStream   outStream = new ByteArrayOutputStream();
-        ByteArrayInputStream    inStream = new ByteArrayInputStream(aBuffer);
-        try {
-            encodeBuffer(inStream, outStream);
-        } catch (Exception IOException) {
-            // This should never happen.
-            throw new Error("CharacterEncoder.encodeBuffer internal error");
-        }
-        return (outStream.toString());
-    }
-
-    /**
-     * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
-     * result to the OutputStream <i>aStream</i>.
-     * <P>
-     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
-     */
-    public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
-        throws IOException {
-        byte [] buf = getBytes(aBuffer);
-        encodeBuffer(buf, aStream);
-    }
-
-    /**
-     * A 'streamless' version of encode that simply takes a ByteBuffer
-     * and returns a string containing the encoded buffer.
-     * <P>
-     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
-     */
-    public String encodeBuffer(ByteBuffer aBuffer) {
-        byte [] buf = getBytes(aBuffer);
-        return encodeBuffer(buf);
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/GC.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/misc/GC.java	Tue Dec 22 13:41:12 2015 -0800
@@ -82,7 +82,7 @@
      */
     public static native long maxObjectInspectionAge();
 
-    private static class Daemon extends ManagedLocalsThread {
+    private static class Daemon extends Thread {
 
         public void run() {
             for (;;) {
@@ -122,7 +122,7 @@
         }
 
         private Daemon(ThreadGroup tg) {
-            super(tg, "GC Daemon");
+            super(tg, null, "GC Daemon", 0L, false);
         }
 
         /* Create a new daemon thread in the root thread group */
--- a/src/java.base/share/classes/sun/misc/HexDumpEncoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.misc;
-import java.io.PrintStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * This class encodes a buffer into the classic: "Hexadecimal Dump" format of
- * the past. It is useful for analyzing the contents of binary buffers.
- * The format produced is as follows:
- * <pre>
- * xxxx: 00 11 22 33 44 55 66 77   88 99 aa bb cc dd ee ff ................
- * </pre>
- * Where xxxx is the offset into the buffer in 16 byte chunks, followed
- * by ascii coded hexadecimal bytes followed by the ASCII representation of
- * the bytes or '.' if they are not valid bytes.
- *
- * @author      Chuck McManis
- */
-
-public class HexDumpEncoder extends CharacterEncoder {
-
-    private int offset;
-    private int thisLineLength;
-    private int currentByte;
-    private byte thisLine[] = new byte[16];
-
-    static void hexDigit(PrintStream p, byte x) {
-        char c;
-
-        c = (char) ((x >> 4) & 0xf);
-        if (c > 9)
-            c = (char) ((c-10) + 'A');
-        else
-            c = (char)(c + '0');
-        p.write(c);
-        c = (char) (x & 0xf);
-        if (c > 9)
-            c = (char)((c-10) + 'A');
-        else
-            c = (char)(c + '0');
-        p.write(c);
-    }
-
-    protected int bytesPerAtom() {
-        return (1);
-    }
-
-    protected int bytesPerLine() {
-        return (16);
-    }
-
-    protected void encodeBufferPrefix(OutputStream o) throws IOException {
-        offset = 0;
-        super.encodeBufferPrefix(o);
-    }
-
-    protected void encodeLinePrefix(OutputStream o, int len) throws IOException {
-        hexDigit(pStream, (byte)((offset >>> 8) & 0xff));
-        hexDigit(pStream, (byte)(offset & 0xff));
-        pStream.print(": ");
-        currentByte = 0;
-        thisLineLength = len;
-    }
-
-    protected void encodeAtom(OutputStream o, byte buf[], int off, int len) throws IOException {
-        thisLine[currentByte] = buf[off];
-        hexDigit(pStream, buf[off]);
-        pStream.print(" ");
-        currentByte++;
-        if (currentByte == 8)
-            pStream.print("  ");
-    }
-
-    protected void encodeLineSuffix(OutputStream o) throws IOException {
-        if (thisLineLength < 16) {
-            for (int i = thisLineLength; i < 16; i++) {
-                pStream.print("   ");
-                if (i == 7)
-                    pStream.print("  ");
-            }
-        }
-        pStream.print(" ");
-        for (int i = 0; i < thisLineLength; i++) {
-            if ((thisLine[i] < ' ') || (thisLine[i] > 'z')) {
-                pStream.print(".");
-            } else {
-                pStream.write(thisLine[i]);
-            }
-        }
-        pStream.println();
-        offset += thisLineLength;
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/InnocuousThread.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/misc/InnocuousThread.java	Tue Dec 22 13:41:12 2015 -0800
@@ -35,8 +35,10 @@
  * A thread that has no permissions, is not a member of any user-defined
  * ThreadGroup and supports the ability to erase ThreadLocals.
  */
-public final class InnocuousThread extends ManagedLocalsThread {
+public final class InnocuousThread extends Thread {
     private static final jdk.internal.misc.Unsafe UNSAFE;
+    private static final long THREAD_LOCALS;
+    private static final long INHERITABLE_THREAD_LOCALS;
     private static final ThreadGroup INNOCUOUSTHREADGROUP;
     private static final AccessControlContext ACC;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
@@ -54,7 +56,7 @@
     }
 
     public InnocuousThread(ThreadGroup group, Runnable target, String name) {
-        super(group, target, name);
+        super(group, target, name, 0L, false);
         UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
         UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
     }
@@ -73,6 +75,14 @@
             throw new SecurityException("setContextClassLoader");
     }
 
+    /**
+     * Drops all thread locals (and inherited thread locals).
+     */
+    public final void eraseThreadLocals() {
+        UNSAFE.putObject(this, THREAD_LOCALS, null);
+        UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+    }
+
     // ensure run method is run only once
     private volatile boolean hasRun;
 
@@ -96,6 +106,10 @@
             Class<?> tk = Thread.class;
             Class<?> gk = ThreadGroup.class;
 
+            THREAD_LOCALS = UNSAFE.objectFieldOffset
+                    (tk.getDeclaredField("threadLocals"));
+            INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
+                    (tk.getDeclaredField("inheritableThreadLocals"));
             INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
                 (tk.getDeclaredField("inheritedAccessControlContext"));
             CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
--- a/src/java.base/share/classes/sun/misc/ProxyGenerator.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2031 +0,0 @@
-/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import sun.security.action.GetBooleanAction;
-
-/**
- * ProxyGenerator contains the code to generate a dynamic proxy class
- * for the java.lang.reflect.Proxy API.
- *
- * The external interfaces to ProxyGenerator is the static
- * "generateProxyClass" method.
- *
- * @author      Peter Jones
- * @since       1.3
- */
-public class ProxyGenerator {
-    /*
-     * In the comments below, "JVMS" refers to The Java Virtual Machine
-     * Specification Second Edition and "JLS" refers to the original
-     * version of The Java Language Specification, unless otherwise
-     * specified.
-     */
-
-    /* generate 1.5-era class file version */
-    private static final int CLASSFILE_MAJOR_VERSION = 49;
-    private static final int CLASSFILE_MINOR_VERSION = 0;
-
-    /*
-     * beginning of constants copied from
-     * sun.tools.java.RuntimeConstants (which no longer exists):
-     */
-
-    /* constant pool tags */
-    private static final int CONSTANT_UTF8              = 1;
-    private static final int CONSTANT_UNICODE           = 2;
-    private static final int CONSTANT_INTEGER           = 3;
-    private static final int CONSTANT_FLOAT             = 4;
-    private static final int CONSTANT_LONG              = 5;
-    private static final int CONSTANT_DOUBLE            = 6;
-    private static final int CONSTANT_CLASS             = 7;
-    private static final int CONSTANT_STRING            = 8;
-    private static final int CONSTANT_FIELD             = 9;
-    private static final int CONSTANT_METHOD            = 10;
-    private static final int CONSTANT_INTERFACEMETHOD   = 11;
-    private static final int CONSTANT_NAMEANDTYPE       = 12;
-
-    /* access and modifier flags */
-    private static final int ACC_PUBLIC                 = 0x00000001;
-    private static final int ACC_PRIVATE                = 0x00000002;
-//  private static final int ACC_PROTECTED              = 0x00000004;
-    private static final int ACC_STATIC                 = 0x00000008;
-    private static final int ACC_FINAL                  = 0x00000010;
-//  private static final int ACC_SYNCHRONIZED           = 0x00000020;
-//  private static final int ACC_VOLATILE               = 0x00000040;
-//  private static final int ACC_TRANSIENT              = 0x00000080;
-//  private static final int ACC_NATIVE                 = 0x00000100;
-//  private static final int ACC_INTERFACE              = 0x00000200;
-//  private static final int ACC_ABSTRACT               = 0x00000400;
-    private static final int ACC_SUPER                  = 0x00000020;
-//  private static final int ACC_STRICT                 = 0x00000800;
-
-    /* opcodes */
-//  private static final int opc_nop                    = 0;
-    private static final int opc_aconst_null            = 1;
-//  private static final int opc_iconst_m1              = 2;
-    private static final int opc_iconst_0               = 3;
-//  private static final int opc_iconst_1               = 4;
-//  private static final int opc_iconst_2               = 5;
-//  private static final int opc_iconst_3               = 6;
-//  private static final int opc_iconst_4               = 7;
-//  private static final int opc_iconst_5               = 8;
-//  private static final int opc_lconst_0               = 9;
-//  private static final int opc_lconst_1               = 10;
-//  private static final int opc_fconst_0               = 11;
-//  private static final int opc_fconst_1               = 12;
-//  private static final int opc_fconst_2               = 13;
-//  private static final int opc_dconst_0               = 14;
-//  private static final int opc_dconst_1               = 15;
-    private static final int opc_bipush                 = 16;
-    private static final int opc_sipush                 = 17;
-    private static final int opc_ldc                    = 18;
-    private static final int opc_ldc_w                  = 19;
-//  private static final int opc_ldc2_w                 = 20;
-    private static final int opc_iload                  = 21;
-    private static final int opc_lload                  = 22;
-    private static final int opc_fload                  = 23;
-    private static final int opc_dload                  = 24;
-    private static final int opc_aload                  = 25;
-    private static final int opc_iload_0                = 26;
-//  private static final int opc_iload_1                = 27;
-//  private static final int opc_iload_2                = 28;
-//  private static final int opc_iload_3                = 29;
-    private static final int opc_lload_0                = 30;
-//  private static final int opc_lload_1                = 31;
-//  private static final int opc_lload_2                = 32;
-//  private static final int opc_lload_3                = 33;
-    private static final int opc_fload_0                = 34;
-//  private static final int opc_fload_1                = 35;
-//  private static final int opc_fload_2                = 36;
-//  private static final int opc_fload_3                = 37;
-    private static final int opc_dload_0                = 38;
-//  private static final int opc_dload_1                = 39;
-//  private static final int opc_dload_2                = 40;
-//  private static final int opc_dload_3                = 41;
-    private static final int opc_aload_0                = 42;
-//  private static final int opc_aload_1                = 43;
-//  private static final int opc_aload_2                = 44;
-//  private static final int opc_aload_3                = 45;
-//  private static final int opc_iaload                 = 46;
-//  private static final int opc_laload                 = 47;
-//  private static final int opc_faload                 = 48;
-//  private static final int opc_daload                 = 49;
-//  private static final int opc_aaload                 = 50;
-//  private static final int opc_baload                 = 51;
-//  private static final int opc_caload                 = 52;
-//  private static final int opc_saload                 = 53;
-//  private static final int opc_istore                 = 54;
-//  private static final int opc_lstore                 = 55;
-//  private static final int opc_fstore                 = 56;
-//  private static final int opc_dstore                 = 57;
-    private static final int opc_astore                 = 58;
-//  private static final int opc_istore_0               = 59;
-//  private static final int opc_istore_1               = 60;
-//  private static final int opc_istore_2               = 61;
-//  private static final int opc_istore_3               = 62;
-//  private static final int opc_lstore_0               = 63;
-//  private static final int opc_lstore_1               = 64;
-//  private static final int opc_lstore_2               = 65;
-//  private static final int opc_lstore_3               = 66;
-//  private static final int opc_fstore_0               = 67;
-//  private static final int opc_fstore_1               = 68;
-//  private static final int opc_fstore_2               = 69;
-//  private static final int opc_fstore_3               = 70;
-//  private static final int opc_dstore_0               = 71;
-//  private static final int opc_dstore_1               = 72;
-//  private static final int opc_dstore_2               = 73;
-//  private static final int opc_dstore_3               = 74;
-    private static final int opc_astore_0               = 75;
-//  private static final int opc_astore_1               = 76;
-//  private static final int opc_astore_2               = 77;
-//  private static final int opc_astore_3               = 78;
-//  private static final int opc_iastore                = 79;
-//  private static final int opc_lastore                = 80;
-//  private static final int opc_fastore                = 81;
-//  private static final int opc_dastore                = 82;
-    private static final int opc_aastore                = 83;
-//  private static final int opc_bastore                = 84;
-//  private static final int opc_castore                = 85;
-//  private static final int opc_sastore                = 86;
-    private static final int opc_pop                    = 87;
-//  private static final int opc_pop2                   = 88;
-    private static final int opc_dup                    = 89;
-//  private static final int opc_dup_x1                 = 90;
-//  private static final int opc_dup_x2                 = 91;
-//  private static final int opc_dup2                   = 92;
-//  private static final int opc_dup2_x1                = 93;
-//  private static final int opc_dup2_x2                = 94;
-//  private static final int opc_swap                   = 95;
-//  private static final int opc_iadd                   = 96;
-//  private static final int opc_ladd                   = 97;
-//  private static final int opc_fadd                   = 98;
-//  private static final int opc_dadd                   = 99;
-//  private static final int opc_isub                   = 100;
-//  private static final int opc_lsub                   = 101;
-//  private static final int opc_fsub                   = 102;
-//  private static final int opc_dsub                   = 103;
-//  private static final int opc_imul                   = 104;
-//  private static final int opc_lmul                   = 105;
-//  private static final int opc_fmul                   = 106;
-//  private static final int opc_dmul                   = 107;
-//  private static final int opc_idiv                   = 108;
-//  private static final int opc_ldiv                   = 109;
-//  private static final int opc_fdiv                   = 110;
-//  private static final int opc_ddiv                   = 111;
-//  private static final int opc_irem                   = 112;
-//  private static final int opc_lrem                   = 113;
-//  private static final int opc_frem                   = 114;
-//  private static final int opc_drem                   = 115;
-//  private static final int opc_ineg                   = 116;
-//  private static final int opc_lneg                   = 117;
-//  private static final int opc_fneg                   = 118;
-//  private static final int opc_dneg                   = 119;
-//  private static final int opc_ishl                   = 120;
-//  private static final int opc_lshl                   = 121;
-//  private static final int opc_ishr                   = 122;
-//  private static final int opc_lshr                   = 123;
-//  private static final int opc_iushr                  = 124;
-//  private static final int opc_lushr                  = 125;
-//  private static final int opc_iand                   = 126;
-//  private static final int opc_land                   = 127;
-//  private static final int opc_ior                    = 128;
-//  private static final int opc_lor                    = 129;
-//  private static final int opc_ixor                   = 130;
-//  private static final int opc_lxor                   = 131;
-//  private static final int opc_iinc                   = 132;
-//  private static final int opc_i2l                    = 133;
-//  private static final int opc_i2f                    = 134;
-//  private static final int opc_i2d                    = 135;
-//  private static final int opc_l2i                    = 136;
-//  private static final int opc_l2f                    = 137;
-//  private static final int opc_l2d                    = 138;
-//  private static final int opc_f2i                    = 139;
-//  private static final int opc_f2l                    = 140;
-//  private static final int opc_f2d                    = 141;
-//  private static final int opc_d2i                    = 142;
-//  private static final int opc_d2l                    = 143;
-//  private static final int opc_d2f                    = 144;
-//  private static final int opc_i2b                    = 145;
-//  private static final int opc_i2c                    = 146;
-//  private static final int opc_i2s                    = 147;
-//  private static final int opc_lcmp                   = 148;
-//  private static final int opc_fcmpl                  = 149;
-//  private static final int opc_fcmpg                  = 150;
-//  private static final int opc_dcmpl                  = 151;
-//  private static final int opc_dcmpg                  = 152;
-//  private static final int opc_ifeq                   = 153;
-//  private static final int opc_ifne                   = 154;
-//  private static final int opc_iflt                   = 155;
-//  private static final int opc_ifge                   = 156;
-//  private static final int opc_ifgt                   = 157;
-//  private static final int opc_ifle                   = 158;
-//  private static final int opc_if_icmpeq              = 159;
-//  private static final int opc_if_icmpne              = 160;
-//  private static final int opc_if_icmplt              = 161;
-//  private static final int opc_if_icmpge              = 162;
-//  private static final int opc_if_icmpgt              = 163;
-//  private static final int opc_if_icmple              = 164;
-//  private static final int opc_if_acmpeq              = 165;
-//  private static final int opc_if_acmpne              = 166;
-//  private static final int opc_goto                   = 167;
-//  private static final int opc_jsr                    = 168;
-//  private static final int opc_ret                    = 169;
-//  private static final int opc_tableswitch            = 170;
-//  private static final int opc_lookupswitch           = 171;
-    private static final int opc_ireturn                = 172;
-    private static final int opc_lreturn                = 173;
-    private static final int opc_freturn                = 174;
-    private static final int opc_dreturn                = 175;
-    private static final int opc_areturn                = 176;
-    private static final int opc_return                 = 177;
-    private static final int opc_getstatic              = 178;
-    private static final int opc_putstatic              = 179;
-    private static final int opc_getfield               = 180;
-//  private static final int opc_putfield               = 181;
-    private static final int opc_invokevirtual          = 182;
-    private static final int opc_invokespecial          = 183;
-    private static final int opc_invokestatic           = 184;
-    private static final int opc_invokeinterface        = 185;
-    private static final int opc_new                    = 187;
-//  private static final int opc_newarray               = 188;
-    private static final int opc_anewarray              = 189;
-//  private static final int opc_arraylength            = 190;
-    private static final int opc_athrow                 = 191;
-    private static final int opc_checkcast              = 192;
-//  private static final int opc_instanceof             = 193;
-//  private static final int opc_monitorenter           = 194;
-//  private static final int opc_monitorexit            = 195;
-    private static final int opc_wide                   = 196;
-//  private static final int opc_multianewarray         = 197;
-//  private static final int opc_ifnull                 = 198;
-//  private static final int opc_ifnonnull              = 199;
-//  private static final int opc_goto_w                 = 200;
-//  private static final int opc_jsr_w                  = 201;
-
-    // end of constants copied from sun.tools.java.RuntimeConstants
-
-    /** name of the superclass of proxy classes */
-    private static final String superclassName = "java/lang/reflect/Proxy";
-
-    /** name of field for storing a proxy instance's invocation handler */
-    private static final String handlerFieldName = "h";
-
-    /** debugging flag for saving generated class files */
-    private static final boolean saveGeneratedFiles =
-        java.security.AccessController.doPrivileged(
-            new GetBooleanAction(
-                "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
-
-    /**
-     * Generate a public proxy class given a name and a list of proxy interfaces.
-     */
-    public static byte[] generateProxyClass(final String name,
-                                            Class<?>[] interfaces) {
-        return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
-    }
-
-    /**
-     * Generate a proxy class given a name and a list of proxy interfaces.
-     *
-     * @param name        the class name of the proxy class
-     * @param interfaces  proxy interfaces
-     * @param accessFlags access flags of the proxy class
-    */
-    public static byte[] generateProxyClass(final String name,
-                                            Class<?>[] interfaces,
-                                            int accessFlags)
-    {
-        ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
-        final byte[] classFile = gen.generateClassFile();
-
-        if (saveGeneratedFiles) {
-            java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                    try {
-                        int i = name.lastIndexOf('.');
-                        Path path;
-                        if (i > 0) {
-                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
-                            Files.createDirectories(dir);
-                            path = dir.resolve(name.substring(i+1, name.length()) + ".class");
-                        } else {
-                            path = Paths.get(name + ".class");
-                        }
-                        Files.write(path, classFile);
-                        return null;
-                    } catch (IOException e) {
-                        throw new InternalError(
-                            "I/O exception saving generated file: " + e);
-                    }
-                }
-            });
-        }
-
-        return classFile;
-    }
-
-    /* preloaded Method objects for methods in java.lang.Object */
-    private static Method hashCodeMethod;
-    private static Method equalsMethod;
-    private static Method toStringMethod;
-    static {
-        try {
-            hashCodeMethod = Object.class.getMethod("hashCode");
-            equalsMethod =
-                Object.class.getMethod("equals", new Class<?>[] { Object.class });
-            toStringMethod = Object.class.getMethod("toString");
-        } catch (NoSuchMethodException e) {
-            throw new NoSuchMethodError(e.getMessage());
-        }
-    }
-
-    /** name of proxy class */
-    private String className;
-
-    /** proxy interfaces */
-    private Class<?>[] interfaces;
-
-    /** proxy class access flags */
-    private int accessFlags;
-
-    /** constant pool of class being generated */
-    private ConstantPool cp = new ConstantPool();
-
-    /** FieldInfo struct for each field of generated class */
-    private List<FieldInfo> fields = new ArrayList<>();
-
-    /** MethodInfo struct for each method of generated class */
-    private List<MethodInfo> methods = new ArrayList<>();
-
-    /**
-     * maps method signature string to list of ProxyMethod objects for
-     * proxy methods with that signature
-     */
-    private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
-
-    /** count of ProxyMethod objects added to proxyMethods */
-    private int proxyMethodCount = 0;
-
-    /**
-     * Construct a ProxyGenerator to generate a proxy class with the
-     * specified name and for the given interfaces.
-     *
-     * A ProxyGenerator object contains the state for the ongoing
-     * generation of a particular proxy class.
-     */
-    private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
-        this.className = className;
-        this.interfaces = interfaces;
-        this.accessFlags = accessFlags;
-    }
-
-    /**
-     * Generate a class file for the proxy class.  This method drives the
-     * class file generation process.
-     */
-    private byte[] generateClassFile() {
-
-        /* ============================================================
-         * Step 1: Assemble ProxyMethod objects for all methods to
-         * generate proxy dispatching code for.
-         */
-
-        /*
-         * Record that proxy methods are needed for the hashCode, equals,
-         * and toString methods of java.lang.Object.  This is done before
-         * the methods from the proxy interfaces so that the methods from
-         * java.lang.Object take precedence over duplicate methods in the
-         * proxy interfaces.
-         */
-        addProxyMethod(hashCodeMethod, Object.class);
-        addProxyMethod(equalsMethod, Object.class);
-        addProxyMethod(toStringMethod, Object.class);
-
-        /*
-         * Now record all of the methods from the proxy interfaces, giving
-         * earlier interfaces precedence over later ones with duplicate
-         * methods.
-         */
-        for (Class<?> intf : interfaces) {
-            for (Method m : intf.getMethods()) {
-                addProxyMethod(m, intf);
-            }
-        }
-
-        /*
-         * For each set of proxy methods with the same signature,
-         * verify that the methods' return types are compatible.
-         */
-        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
-            checkReturnTypes(sigmethods);
-        }
-
-        /* ============================================================
-         * Step 2: Assemble FieldInfo and MethodInfo structs for all of
-         * fields and methods in the class we are generating.
-         */
-        try {
-            methods.add(generateConstructor());
-
-            for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
-                for (ProxyMethod pm : sigmethods) {
-
-                    // add static field for method's Method object
-                    fields.add(new FieldInfo(pm.methodFieldName,
-                        "Ljava/lang/reflect/Method;",
-                         ACC_PRIVATE | ACC_STATIC));
-
-                    // generate code for proxy method and add it
-                    methods.add(pm.generateMethod());
-                }
-            }
-
-            methods.add(generateStaticInitializer());
-
-        } catch (IOException e) {
-            throw new InternalError("unexpected I/O Exception", e);
-        }
-
-        if (methods.size() > 65535) {
-            throw new IllegalArgumentException("method limit exceeded");
-        }
-        if (fields.size() > 65535) {
-            throw new IllegalArgumentException("field limit exceeded");
-        }
-
-        /* ============================================================
-         * Step 3: Write the final class file.
-         */
-
-        /*
-         * Make sure that constant pool indexes are reserved for the
-         * following items before starting to write the final class file.
-         */
-        cp.getClass(dotToSlash(className));
-        cp.getClass(superclassName);
-        for (Class<?> intf: interfaces) {
-            cp.getClass(dotToSlash(intf.getName()));
-        }
-
-        /*
-         * Disallow new constant pool additions beyond this point, since
-         * we are about to write the final constant pool table.
-         */
-        cp.setReadOnly();
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        DataOutputStream dout = new DataOutputStream(bout);
-
-        try {
-            /*
-             * Write all the items of the "ClassFile" structure.
-             * See JVMS section 4.1.
-             */
-                                        // u4 magic;
-            dout.writeInt(0xCAFEBABE);
-                                        // u2 minor_version;
-            dout.writeShort(CLASSFILE_MINOR_VERSION);
-                                        // u2 major_version;
-            dout.writeShort(CLASSFILE_MAJOR_VERSION);
-
-            cp.write(dout);             // (write constant pool)
-
-                                        // u2 access_flags;
-            dout.writeShort(accessFlags);
-                                        // u2 this_class;
-            dout.writeShort(cp.getClass(dotToSlash(className)));
-                                        // u2 super_class;
-            dout.writeShort(cp.getClass(superclassName));
-
-                                        // u2 interfaces_count;
-            dout.writeShort(interfaces.length);
-                                        // u2 interfaces[interfaces_count];
-            for (Class<?> intf : interfaces) {
-                dout.writeShort(cp.getClass(
-                    dotToSlash(intf.getName())));
-            }
-
-                                        // u2 fields_count;
-            dout.writeShort(fields.size());
-                                        // field_info fields[fields_count];
-            for (FieldInfo f : fields) {
-                f.write(dout);
-            }
-
-                                        // u2 methods_count;
-            dout.writeShort(methods.size());
-                                        // method_info methods[methods_count];
-            for (MethodInfo m : methods) {
-                m.write(dout);
-            }
-
-                                         // u2 attributes_count;
-            dout.writeShort(0); // (no ClassFile attributes for proxy classes)
-
-        } catch (IOException e) {
-            throw new InternalError("unexpected I/O Exception", e);
-        }
-
-        return bout.toByteArray();
-    }
-
-    /**
-     * Add another method to be proxied, either by creating a new
-     * ProxyMethod object or augmenting an old one for a duplicate
-     * method.
-     *
-     * "fromClass" indicates the proxy interface that the method was
-     * found through, which may be different from (a subinterface of)
-     * the method's "declaring class".  Note that the first Method
-     * object passed for a given name and descriptor identifies the
-     * Method object (and thus the declaring class) that will be
-     * passed to the invocation handler's "invoke" method for a given
-     * set of duplicate methods.
-     */
-    private void addProxyMethod(Method m, Class<?> fromClass) {
-        String name = m.getName();
-        Class<?>[] parameterTypes = m.getParameterTypes();
-        Class<?> returnType = m.getReturnType();
-        Class<?>[] exceptionTypes = m.getExceptionTypes();
-
-        String sig = name + getParameterDescriptors(parameterTypes);
-        List<ProxyMethod> sigmethods = proxyMethods.get(sig);
-        if (sigmethods != null) {
-            for (ProxyMethod pm : sigmethods) {
-                if (returnType == pm.returnType) {
-                    /*
-                     * Found a match: reduce exception types to the
-                     * greatest set of exceptions that can thrown
-                     * compatibly with the throws clauses of both
-                     * overridden methods.
-                     */
-                    List<Class<?>> legalExceptions = new ArrayList<>();
-                    collectCompatibleTypes(
-                        exceptionTypes, pm.exceptionTypes, legalExceptions);
-                    collectCompatibleTypes(
-                        pm.exceptionTypes, exceptionTypes, legalExceptions);
-                    pm.exceptionTypes = new Class<?>[legalExceptions.size()];
-                    pm.exceptionTypes =
-                        legalExceptions.toArray(pm.exceptionTypes);
-                    return;
-                }
-            }
-        } else {
-            sigmethods = new ArrayList<>(3);
-            proxyMethods.put(sig, sigmethods);
-        }
-        sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
-                                       exceptionTypes, fromClass));
-    }
-
-    /**
-     * For a given set of proxy methods with the same signature, check
-     * that their return types are compatible according to the Proxy
-     * specification.
-     *
-     * Specifically, if there is more than one such method, then all
-     * of the return types must be reference types, and there must be
-     * one return type that is assignable to each of the rest of them.
-     */
-    private static void checkReturnTypes(List<ProxyMethod> methods) {
-        /*
-         * If there is only one method with a given signature, there
-         * cannot be a conflict.  This is the only case in which a
-         * primitive (or void) return type is allowed.
-         */
-        if (methods.size() < 2) {
-            return;
-        }
-
-        /*
-         * List of return types that are not yet known to be
-         * assignable from ("covered" by) any of the others.
-         */
-        LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
-
-    nextNewReturnType:
-        for (ProxyMethod pm : methods) {
-            Class<?> newReturnType = pm.returnType;
-            if (newReturnType.isPrimitive()) {
-                throw new IllegalArgumentException(
-                    "methods with same signature " +
-                    getFriendlyMethodSignature(pm.methodName,
-                                               pm.parameterTypes) +
-                    " but incompatible return types: " +
-                    newReturnType.getName() + " and others");
-            }
-            boolean added = false;
-
-            /*
-             * Compare the new return type to the existing uncovered
-             * return types.
-             */
-            ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
-            while (liter.hasNext()) {
-                Class<?> uncoveredReturnType = liter.next();
-
-                /*
-                 * If an existing uncovered return type is assignable
-                 * to this new one, then we can forget the new one.
-                 */
-                if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
-                    assert !added;
-                    continue nextNewReturnType;
-                }
-
-                /*
-                 * If the new return type is assignable to an existing
-                 * uncovered one, then should replace the existing one
-                 * with the new one (or just forget the existing one,
-                 * if the new one has already be put in the list).
-                 */
-                if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
-                    // (we can assume that each return type is unique)
-                    if (!added) {
-                        liter.set(newReturnType);
-                        added = true;
-                    } else {
-                        liter.remove();
-                    }
-                }
-            }
-
-            /*
-             * If we got through the list of existing uncovered return
-             * types without an assignability relationship, then add
-             * the new return type to the list of uncovered ones.
-             */
-            if (!added) {
-                uncoveredReturnTypes.add(newReturnType);
-            }
-        }
-
-        /*
-         * We shouldn't end up with more than one return type that is
-         * not assignable from any of the others.
-         */
-        if (uncoveredReturnTypes.size() > 1) {
-            ProxyMethod pm = methods.get(0);
-            throw new IllegalArgumentException(
-                "methods with same signature " +
-                getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
-                " but incompatible return types: " + uncoveredReturnTypes);
-        }
-    }
-
-    /**
-     * A FieldInfo object contains information about a particular field
-     * in the class being generated.  The class mirrors the data items of
-     * the "field_info" structure of the class file format (see JVMS 4.5).
-     */
-    private class FieldInfo {
-        public int accessFlags;
-        public String name;
-        public String descriptor;
-
-        public FieldInfo(String name, String descriptor, int accessFlags) {
-            this.name = name;
-            this.descriptor = descriptor;
-            this.accessFlags = accessFlags;
-
-            /*
-             * Make sure that constant pool indexes are reserved for the
-             * following items before starting to write the final class file.
-             */
-            cp.getUtf8(name);
-            cp.getUtf8(descriptor);
-        }
-
-        public void write(DataOutputStream out) throws IOException {
-            /*
-             * Write all the items of the "field_info" structure.
-             * See JVMS section 4.5.
-             */
-                                        // u2 access_flags;
-            out.writeShort(accessFlags);
-                                        // u2 name_index;
-            out.writeShort(cp.getUtf8(name));
-                                        // u2 descriptor_index;
-            out.writeShort(cp.getUtf8(descriptor));
-                                        // u2 attributes_count;
-            out.writeShort(0);  // (no field_info attributes for proxy classes)
-        }
-    }
-
-    /**
-     * An ExceptionTableEntry object holds values for the data items of
-     * an entry in the "exception_table" item of the "Code" attribute of
-     * "method_info" structures (see JVMS 4.7.3).
-     */
-    private static class ExceptionTableEntry {
-        public short startPc;
-        public short endPc;
-        public short handlerPc;
-        public short catchType;
-
-        public ExceptionTableEntry(short startPc, short endPc,
-                                   short handlerPc, short catchType)
-        {
-            this.startPc = startPc;
-            this.endPc = endPc;
-            this.handlerPc = handlerPc;
-            this.catchType = catchType;
-        }
-    };
-
-    /**
-     * A MethodInfo object contains information about a particular method
-     * in the class being generated.  This class mirrors the data items of
-     * the "method_info" structure of the class file format (see JVMS 4.6).
-     */
-    private class MethodInfo {
-        public int accessFlags;
-        public String name;
-        public String descriptor;
-        public short maxStack;
-        public short maxLocals;
-        public ByteArrayOutputStream code = new ByteArrayOutputStream();
-        public List<ExceptionTableEntry> exceptionTable =
-            new ArrayList<ExceptionTableEntry>();
-        public short[] declaredExceptions;
-
-        public MethodInfo(String name, String descriptor, int accessFlags) {
-            this.name = name;
-            this.descriptor = descriptor;
-            this.accessFlags = accessFlags;
-
-            /*
-             * Make sure that constant pool indexes are reserved for the
-             * following items before starting to write the final class file.
-             */
-            cp.getUtf8(name);
-            cp.getUtf8(descriptor);
-            cp.getUtf8("Code");
-            cp.getUtf8("Exceptions");
-        }
-
-        public void write(DataOutputStream out) throws IOException {
-            /*
-             * Write all the items of the "method_info" structure.
-             * See JVMS section 4.6.
-             */
-                                        // u2 access_flags;
-            out.writeShort(accessFlags);
-                                        // u2 name_index;
-            out.writeShort(cp.getUtf8(name));
-                                        // u2 descriptor_index;
-            out.writeShort(cp.getUtf8(descriptor));
-                                        // u2 attributes_count;
-            out.writeShort(2);  // (two method_info attributes:)
-
-            // Write "Code" attribute. See JVMS section 4.7.3.
-
-                                        // u2 attribute_name_index;
-            out.writeShort(cp.getUtf8("Code"));
-                                        // u4 attribute_length;
-            out.writeInt(12 + code.size() + 8 * exceptionTable.size());
-                                        // u2 max_stack;
-            out.writeShort(maxStack);
-                                        // u2 max_locals;
-            out.writeShort(maxLocals);
-                                        // u2 code_length;
-            out.writeInt(code.size());
-                                        // u1 code[code_length];
-            code.writeTo(out);
-                                        // u2 exception_table_length;
-            out.writeShort(exceptionTable.size());
-            for (ExceptionTableEntry e : exceptionTable) {
-                                        // u2 start_pc;
-                out.writeShort(e.startPc);
-                                        // u2 end_pc;
-                out.writeShort(e.endPc);
-                                        // u2 handler_pc;
-                out.writeShort(e.handlerPc);
-                                        // u2 catch_type;
-                out.writeShort(e.catchType);
-            }
-                                        // u2 attributes_count;
-            out.writeShort(0);
-
-            // write "Exceptions" attribute.  See JVMS section 4.7.4.
-
-                                        // u2 attribute_name_index;
-            out.writeShort(cp.getUtf8("Exceptions"));
-                                        // u4 attributes_length;
-            out.writeInt(2 + 2 * declaredExceptions.length);
-                                        // u2 number_of_exceptions;
-            out.writeShort(declaredExceptions.length);
-                        // u2 exception_index_table[number_of_exceptions];
-            for (short value : declaredExceptions) {
-                out.writeShort(value);
-            }
-        }
-
-    }
-
-    /**
-     * A ProxyMethod object represents a proxy method in the proxy class
-     * being generated: a method whose implementation will encode and
-     * dispatch invocations to the proxy instance's invocation handler.
-     */
-    private class ProxyMethod {
-
-        public String methodName;
-        public Class<?>[] parameterTypes;
-        public Class<?> returnType;
-        public Class<?>[] exceptionTypes;
-        public Class<?> fromClass;
-        public String methodFieldName;
-
-        private ProxyMethod(String methodName, Class<?>[] parameterTypes,
-                            Class<?> returnType, Class<?>[] exceptionTypes,
-                            Class<?> fromClass)
-        {
-            this.methodName = methodName;
-            this.parameterTypes = parameterTypes;
-            this.returnType = returnType;
-            this.exceptionTypes = exceptionTypes;
-            this.fromClass = fromClass;
-            this.methodFieldName = "m" + proxyMethodCount++;
-        }
-
-        /**
-         * Return a MethodInfo object for this method, including generating
-         * the code and exception table entry.
-         */
-        private MethodInfo generateMethod() throws IOException {
-            String desc = getMethodDescriptor(parameterTypes, returnType);
-            MethodInfo minfo = new MethodInfo(methodName, desc,
-                ACC_PUBLIC | ACC_FINAL);
-
-            int[] parameterSlot = new int[parameterTypes.length];
-            int nextSlot = 1;
-            for (int i = 0; i < parameterSlot.length; i++) {
-                parameterSlot[i] = nextSlot;
-                nextSlot += getWordsPerType(parameterTypes[i]);
-            }
-            int localSlot0 = nextSlot;
-            short pc, tryBegin = 0, tryEnd;
-
-            DataOutputStream out = new DataOutputStream(minfo.code);
-
-            code_aload(0, out);
-
-            out.writeByte(opc_getfield);
-            out.writeShort(cp.getFieldRef(
-                superclassName,
-                handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
-
-            code_aload(0, out);
-
-            out.writeByte(opc_getstatic);
-            out.writeShort(cp.getFieldRef(
-                dotToSlash(className),
-                methodFieldName, "Ljava/lang/reflect/Method;"));
-
-            if (parameterTypes.length > 0) {
-
-                code_ipush(parameterTypes.length, out);
-
-                out.writeByte(opc_anewarray);
-                out.writeShort(cp.getClass("java/lang/Object"));
-
-                for (int i = 0; i < parameterTypes.length; i++) {
-
-                    out.writeByte(opc_dup);
-
-                    code_ipush(i, out);
-
-                    codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
-
-                    out.writeByte(opc_aastore);
-                }
-            } else {
-
-                out.writeByte(opc_aconst_null);
-            }
-
-            out.writeByte(opc_invokeinterface);
-            out.writeShort(cp.getInterfaceMethodRef(
-                "java/lang/reflect/InvocationHandler",
-                "invoke",
-                "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
-                    "[Ljava/lang/Object;)Ljava/lang/Object;"));
-            out.writeByte(4);
-            out.writeByte(0);
-
-            if (returnType == void.class) {
-
-                out.writeByte(opc_pop);
-
-                out.writeByte(opc_return);
-
-            } else {
-
-                codeUnwrapReturnValue(returnType, out);
-            }
-
-            tryEnd = pc = (short) minfo.code.size();
-
-            List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
-            if (catchList.size() > 0) {
-
-                for (Class<?> ex : catchList) {
-                    minfo.exceptionTable.add(new ExceptionTableEntry(
-                        tryBegin, tryEnd, pc,
-                        cp.getClass(dotToSlash(ex.getName()))));
-                }
-
-                out.writeByte(opc_athrow);
-
-                pc = (short) minfo.code.size();
-
-                minfo.exceptionTable.add(new ExceptionTableEntry(
-                    tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
-
-                code_astore(localSlot0, out);
-
-                out.writeByte(opc_new);
-                out.writeShort(cp.getClass(
-                    "java/lang/reflect/UndeclaredThrowableException"));
-
-                out.writeByte(opc_dup);
-
-                code_aload(localSlot0, out);
-
-                out.writeByte(opc_invokespecial);
-
-                out.writeShort(cp.getMethodRef(
-                    "java/lang/reflect/UndeclaredThrowableException",
-                    "<init>", "(Ljava/lang/Throwable;)V"));
-
-                out.writeByte(opc_athrow);
-            }
-
-            if (minfo.code.size() > 65535) {
-                throw new IllegalArgumentException("code size limit exceeded");
-            }
-
-            minfo.maxStack = 10;
-            minfo.maxLocals = (short) (localSlot0 + 1);
-            minfo.declaredExceptions = new short[exceptionTypes.length];
-            for (int i = 0; i < exceptionTypes.length; i++) {
-                minfo.declaredExceptions[i] = cp.getClass(
-                    dotToSlash(exceptionTypes[i].getName()));
-            }
-
-            return minfo;
-        }
-
-        /**
-         * Generate code for wrapping an argument of the given type
-         * whose value can be found at the specified local variable
-         * index, in order for it to be passed (as an Object) to the
-         * invocation handler's "invoke" method.  The code is written
-         * to the supplied stream.
-         */
-        private void codeWrapArgument(Class<?> type, int slot,
-                                      DataOutputStream out)
-            throws IOException
-        {
-            if (type.isPrimitive()) {
-                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
-
-                if (type == int.class ||
-                    type == boolean.class ||
-                    type == byte.class ||
-                    type == char.class ||
-                    type == short.class)
-                {
-                    code_iload(slot, out);
-                } else if (type == long.class) {
-                    code_lload(slot, out);
-                } else if (type == float.class) {
-                    code_fload(slot, out);
-                } else if (type == double.class) {
-                    code_dload(slot, out);
-                } else {
-                    throw new AssertionError();
-                }
-
-                out.writeByte(opc_invokestatic);
-                out.writeShort(cp.getMethodRef(
-                    prim.wrapperClassName,
-                    "valueOf", prim.wrapperValueOfDesc));
-
-            } else {
-
-                code_aload(slot, out);
-            }
-        }
-
-        /**
-         * Generate code for unwrapping a return value of the given
-         * type from the invocation handler's "invoke" method (as type
-         * Object) to its correct type.  The code is written to the
-         * supplied stream.
-         */
-        private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out)
-            throws IOException
-        {
-            if (type.isPrimitive()) {
-                PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
-
-                out.writeByte(opc_checkcast);
-                out.writeShort(cp.getClass(prim.wrapperClassName));
-
-                out.writeByte(opc_invokevirtual);
-                out.writeShort(cp.getMethodRef(
-                    prim.wrapperClassName,
-                    prim.unwrapMethodName, prim.unwrapMethodDesc));
-
-                if (type == int.class ||
-                    type == boolean.class ||
-                    type == byte.class ||
-                    type == char.class ||
-                    type == short.class)
-                {
-                    out.writeByte(opc_ireturn);
-                } else if (type == long.class) {
-                    out.writeByte(opc_lreturn);
-                } else if (type == float.class) {
-                    out.writeByte(opc_freturn);
-                } else if (type == double.class) {
-                    out.writeByte(opc_dreturn);
-                } else {
-                    throw new AssertionError();
-                }
-
-            } else {
-
-                out.writeByte(opc_checkcast);
-                out.writeShort(cp.getClass(dotToSlash(type.getName())));
-
-                out.writeByte(opc_areturn);
-            }
-        }
-
-        /**
-         * Generate code for initializing the static field that stores
-         * the Method object for this proxy method.  The code is written
-         * to the supplied stream.
-         */
-        private void codeFieldInitialization(DataOutputStream out)
-            throws IOException
-        {
-            codeClassForName(fromClass, out);
-
-            code_ldc(cp.getString(methodName), out);
-
-            code_ipush(parameterTypes.length, out);
-
-            out.writeByte(opc_anewarray);
-            out.writeShort(cp.getClass("java/lang/Class"));
-
-            for (int i = 0; i < parameterTypes.length; i++) {
-
-                out.writeByte(opc_dup);
-
-                code_ipush(i, out);
-
-                if (parameterTypes[i].isPrimitive()) {
-                    PrimitiveTypeInfo prim =
-                        PrimitiveTypeInfo.get(parameterTypes[i]);
-
-                    out.writeByte(opc_getstatic);
-                    out.writeShort(cp.getFieldRef(
-                        prim.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
-
-                } else {
-                    codeClassForName(parameterTypes[i], out);
-                }
-
-                out.writeByte(opc_aastore);
-            }
-
-            out.writeByte(opc_invokevirtual);
-            out.writeShort(cp.getMethodRef(
-                "java/lang/Class",
-                "getMethod",
-                "(Ljava/lang/String;[Ljava/lang/Class;)" +
-                "Ljava/lang/reflect/Method;"));
-
-            out.writeByte(opc_putstatic);
-            out.writeShort(cp.getFieldRef(
-                dotToSlash(className),
-                methodFieldName, "Ljava/lang/reflect/Method;"));
-        }
-    }
-
-    /**
-     * Generate the constructor method for the proxy class.
-     */
-    private MethodInfo generateConstructor() throws IOException {
-        MethodInfo minfo = new MethodInfo(
-            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
-            ACC_PUBLIC);
-
-        DataOutputStream out = new DataOutputStream(minfo.code);
-
-        code_aload(0, out);
-
-        code_aload(1, out);
-
-        out.writeByte(opc_invokespecial);
-        out.writeShort(cp.getMethodRef(
-            superclassName,
-            "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
-
-        out.writeByte(opc_return);
-
-        minfo.maxStack = 10;
-        minfo.maxLocals = 2;
-        minfo.declaredExceptions = new short[0];
-
-        return minfo;
-    }
-
-    /**
-     * Generate the static initializer method for the proxy class.
-     */
-    private MethodInfo generateStaticInitializer() throws IOException {
-        MethodInfo minfo = new MethodInfo(
-            "<clinit>", "()V", ACC_STATIC);
-
-        int localSlot0 = 1;
-        short pc, tryBegin = 0, tryEnd;
-
-        DataOutputStream out = new DataOutputStream(minfo.code);
-
-        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
-            for (ProxyMethod pm : sigmethods) {
-                pm.codeFieldInitialization(out);
-            }
-        }
-
-        out.writeByte(opc_return);
-
-        tryEnd = pc = (short) minfo.code.size();
-
-        minfo.exceptionTable.add(new ExceptionTableEntry(
-            tryBegin, tryEnd, pc,
-            cp.getClass("java/lang/NoSuchMethodException")));
-
-        code_astore(localSlot0, out);
-
-        out.writeByte(opc_new);
-        out.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
-
-        out.writeByte(opc_dup);
-
-        code_aload(localSlot0, out);
-
-        out.writeByte(opc_invokevirtual);
-        out.writeShort(cp.getMethodRef(
-            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
-
-        out.writeByte(opc_invokespecial);
-        out.writeShort(cp.getMethodRef(
-            "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
-
-        out.writeByte(opc_athrow);
-
-        pc = (short) minfo.code.size();
-
-        minfo.exceptionTable.add(new ExceptionTableEntry(
-            tryBegin, tryEnd, pc,
-            cp.getClass("java/lang/ClassNotFoundException")));
-
-        code_astore(localSlot0, out);
-
-        out.writeByte(opc_new);
-        out.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
-
-        out.writeByte(opc_dup);
-
-        code_aload(localSlot0, out);
-
-        out.writeByte(opc_invokevirtual);
-        out.writeShort(cp.getMethodRef(
-            "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
-
-        out.writeByte(opc_invokespecial);
-        out.writeShort(cp.getMethodRef(
-            "java/lang/NoClassDefFoundError",
-            "<init>", "(Ljava/lang/String;)V"));
-
-        out.writeByte(opc_athrow);
-
-        if (minfo.code.size() > 65535) {
-            throw new IllegalArgumentException("code size limit exceeded");
-        }
-
-        minfo.maxStack = 10;
-        minfo.maxLocals = (short) (localSlot0 + 1);
-        minfo.declaredExceptions = new short[0];
-
-        return minfo;
-    }
-
-
-    /*
-     * =============== Code Generation Utility Methods ===============
-     */
-
-    /*
-     * The following methods generate code for the load or store operation
-     * indicated by their name for the given local variable.  The code is
-     * written to the supplied stream.
-     */
-
-    private void code_iload(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out);
-    }
-
-    private void code_lload(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out);
-    }
-
-    private void code_fload(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out);
-    }
-
-    private void code_dload(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out);
-    }
-
-    private void code_aload(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out);
-    }
-
-//  private void code_istore(int lvar, DataOutputStream out)
-//      throws IOException
-//  {
-//      codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
-//  }
-
-//  private void code_lstore(int lvar, DataOutputStream out)
-//      throws IOException
-//  {
-//      codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
-//  }
-
-//  private void code_fstore(int lvar, DataOutputStream out)
-//      throws IOException
-//  {
-//      codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
-//  }
-
-//  private void code_dstore(int lvar, DataOutputStream out)
-//      throws IOException
-//  {
-//      codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
-//  }
-
-    private void code_astore(int lvar, DataOutputStream out)
-        throws IOException
-    {
-        codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out);
-    }
-
-    /**
-     * Generate code for a load or store instruction for the given local
-     * variable.  The code is written to the supplied stream.
-     *
-     * "opcode" indicates the opcode form of the desired load or store
-     * instruction that takes an explicit local variable index, and
-     * "opcode_0" indicates the corresponding form of the instruction
-     * with the implicit index 0.
-     */
-    private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
-                                    DataOutputStream out)
-        throws IOException
-    {
-        assert lvar >= 0 && lvar <= 0xFFFF;
-        if (lvar <= 3) {
-            out.writeByte(opcode_0 + lvar);
-        } else if (lvar <= 0xFF) {
-            out.writeByte(opcode);
-            out.writeByte(lvar & 0xFF);
-        } else {
-            /*
-             * Use the "wide" instruction modifier for local variable
-             * indexes that do not fit into an unsigned byte.
-             */
-            out.writeByte(opc_wide);
-            out.writeByte(opcode);
-            out.writeShort(lvar & 0xFFFF);
-        }
-    }
-
-    /**
-     * Generate code for an "ldc" instruction for the given constant pool
-     * index (the "ldc_w" instruction is used if the index does not fit
-     * into an unsigned byte).  The code is written to the supplied stream.
-     */
-    private void code_ldc(int index, DataOutputStream out)
-        throws IOException
-    {
-        assert index >= 0 && index <= 0xFFFF;
-        if (index <= 0xFF) {
-            out.writeByte(opc_ldc);
-            out.writeByte(index & 0xFF);
-        } else {
-            out.writeByte(opc_ldc_w);
-            out.writeShort(index & 0xFFFF);
-        }
-    }
-
-    /**
-     * Generate code to push a constant integer value on to the operand
-     * stack, using the "iconst_<i>", "bipush", or "sipush" instructions
-     * depending on the size of the value.  The code is written to the
-     * supplied stream.
-     */
-    private void code_ipush(int value, DataOutputStream out)
-        throws IOException
-    {
-        if (value >= -1 && value <= 5) {
-            out.writeByte(opc_iconst_0 + value);
-        } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
-            out.writeByte(opc_bipush);
-            out.writeByte(value & 0xFF);
-        } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
-            out.writeByte(opc_sipush);
-            out.writeShort(value & 0xFFFF);
-        } else {
-            throw new AssertionError();
-        }
-    }
-
-    /**
-     * Generate code to invoke the Class.forName with the name of the given
-     * class to get its Class object at runtime.  The code is written to
-     * the supplied stream.  Note that the code generated by this method
-     * may caused the checked ClassNotFoundException to be thrown.
-     */
-    private void codeClassForName(Class<?> cl, DataOutputStream out)
-        throws IOException
-    {
-        code_ldc(cp.getString(cl.getName()), out);
-
-        out.writeByte(opc_invokestatic);
-        out.writeShort(cp.getMethodRef(
-            "java/lang/Class",
-            "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
-    }
-
-
-    /*
-     * ==================== General Utility Methods ====================
-     */
-
-    /**
-     * Convert a fully qualified class name that uses '.' as the package
-     * separator, the external representation used by the Java language
-     * and APIs, to a fully qualified class name that uses '/' as the
-     * package separator, the representation used in the class file
-     * format (see JVMS section 4.2).
-     */
-    private static String dotToSlash(String name) {
-        return name.replace('.', '/');
-    }
-
-    /**
-     * Return the "method descriptor" string for a method with the given
-     * parameter types and return type.  See JVMS section 4.3.3.
-     */
-    private static String getMethodDescriptor(Class<?>[] parameterTypes,
-                                              Class<?> returnType)
-    {
-        return getParameterDescriptors(parameterTypes) +
-            ((returnType == void.class) ? "V" : getFieldType(returnType));
-    }
-
-    /**
-     * Return the list of "parameter descriptor" strings enclosed in
-     * parentheses corresponding to the given parameter types (in other
-     * words, a method descriptor without a return descriptor).  This
-     * string is useful for constructing string keys for methods without
-     * regard to their return type.
-     */
-    private static String getParameterDescriptors(Class<?>[] parameterTypes) {
-        StringBuilder desc = new StringBuilder("(");
-        for (int i = 0; i < parameterTypes.length; i++) {
-            desc.append(getFieldType(parameterTypes[i]));
-        }
-        desc.append(')');
-        return desc.toString();
-    }
-
-    /**
-     * Return the "field type" string for the given type, appropriate for
-     * a field descriptor, a parameter descriptor, or a return descriptor
-     * other than "void".  See JVMS section 4.3.2.
-     */
-    private static String getFieldType(Class<?> type) {
-        if (type.isPrimitive()) {
-            return PrimitiveTypeInfo.get(type).baseTypeString;
-        } else if (type.isArray()) {
-            /*
-             * According to JLS 20.3.2, the getName() method on Class does
-             * return the VM type descriptor format for array classes (only);
-             * using that should be quicker than the otherwise obvious code:
-             *
-             *     return "[" + getTypeDescriptor(type.getComponentType());
-             */
-            return type.getName().replace('.', '/');
-        } else {
-            return "L" + dotToSlash(type.getName()) + ";";
-        }
-    }
-
-    /**
-     * Returns a human-readable string representing the signature of a
-     * method with the given name and parameter types.
-     */
-    private static String getFriendlyMethodSignature(String name,
-                                                     Class<?>[] parameterTypes)
-    {
-        StringBuilder sig = new StringBuilder(name);
-        sig.append('(');
-        for (int i = 0; i < parameterTypes.length; i++) {
-            if (i > 0) {
-                sig.append(',');
-            }
-            Class<?> parameterType = parameterTypes[i];
-            int dimensions = 0;
-            while (parameterType.isArray()) {
-                parameterType = parameterType.getComponentType();
-                dimensions++;
-            }
-            sig.append(parameterType.getName());
-            while (dimensions-- > 0) {
-                sig.append("[]");
-            }
-        }
-        sig.append(')');
-        return sig.toString();
-    }
-
-    /**
-     * Return the number of abstract "words", or consecutive local variable
-     * indexes, required to contain a value of the given type.  See JVMS
-     * section 3.6.1.
-     *
-     * Note that the original version of the JVMS contained a definition of
-     * this abstract notion of a "word" in section 3.4, but that definition
-     * was removed for the second edition.
-     */
-    private static int getWordsPerType(Class<?> type) {
-        if (type == long.class || type == double.class) {
-            return 2;
-        } else {
-            return 1;
-        }
-    }
-
-    /**
-     * Add to the given list all of the types in the "from" array that
-     * are not already contained in the list and are assignable to at
-     * least one of the types in the "with" array.
-     *
-     * This method is useful for computing the greatest common set of
-     * declared exceptions from duplicate methods inherited from
-     * different interfaces.
-     */
-    private static void collectCompatibleTypes(Class<?>[] from,
-                                               Class<?>[] with,
-                                               List<Class<?>> list)
-    {
-        for (Class<?> fc: from) {
-            if (!list.contains(fc)) {
-                for (Class<?> wc: with) {
-                    if (wc.isAssignableFrom(fc)) {
-                        list.add(fc);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Given the exceptions declared in the throws clause of a proxy method,
-     * compute the exceptions that need to be caught from the invocation
-     * handler's invoke method and rethrown intact in the method's
-     * implementation before catching other Throwables and wrapping them
-     * in UndeclaredThrowableExceptions.
-     *
-     * The exceptions to be caught are returned in a List object.  Each
-     * exception in the returned list is guaranteed to not be a subclass of
-     * any of the other exceptions in the list, so the catch blocks for
-     * these exceptions may be generated in any order relative to each other.
-     *
-     * Error and RuntimeException are each always contained by the returned
-     * list (if none of their superclasses are contained), since those
-     * unchecked exceptions should always be rethrown intact, and thus their
-     * subclasses will never appear in the returned list.
-     *
-     * The returned List will be empty if java.lang.Throwable is in the
-     * given list of declared exceptions, indicating that no exceptions
-     * need to be caught.
-     */
-    private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
-        List<Class<?>> uniqueList = new ArrayList<>();
-                                                // unique exceptions to catch
-
-        uniqueList.add(Error.class);            // always catch/rethrow these
-        uniqueList.add(RuntimeException.class);
-
-    nextException:
-        for (Class<?> ex: exceptions) {
-            if (ex.isAssignableFrom(Throwable.class)) {
-                /*
-                 * If Throwable is declared to be thrown by the proxy method,
-                 * then no catch blocks are necessary, because the invoke
-                 * can, at most, throw Throwable anyway.
-                 */
-                uniqueList.clear();
-                break;
-            } else if (!Throwable.class.isAssignableFrom(ex)) {
-                /*
-                 * Ignore types that cannot be thrown by the invoke method.
-                 */
-                continue;
-            }
-            /*
-             * Compare this exception against the current list of
-             * exceptions that need to be caught:
-             */
-            for (int j = 0; j < uniqueList.size();) {
-                Class<?> ex2 = uniqueList.get(j);
-                if (ex2.isAssignableFrom(ex)) {
-                    /*
-                     * if a superclass of this exception is already on
-                     * the list to catch, then ignore this one and continue;
-                     */
-                    continue nextException;
-                } else if (ex.isAssignableFrom(ex2)) {
-                    /*
-                     * if a subclass of this exception is on the list
-                     * to catch, then remove it;
-                     */
-                    uniqueList.remove(j);
-                } else {
-                    j++;        // else continue comparing.
-                }
-            }
-            // This exception is unique (so far): add it to the list to catch.
-            uniqueList.add(ex);
-        }
-        return uniqueList;
-    }
-
-    /**
-     * A PrimitiveTypeInfo object contains assorted information about
-     * a primitive type in its public fields.  The struct for a particular
-     * primitive type can be obtained using the static "get" method.
-     */
-    private static class PrimitiveTypeInfo {
-
-        /** "base type" used in various descriptors (see JVMS section 4.3.2) */
-        public String baseTypeString;
-
-        /** name of corresponding wrapper class */
-        public String wrapperClassName;
-
-        /** method descriptor for wrapper class "valueOf" factory method */
-        public String wrapperValueOfDesc;
-
-        /** name of wrapper class method for retrieving primitive value */
-        public String unwrapMethodName;
-
-        /** descriptor of same method */
-        public String unwrapMethodDesc;
-
-        private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>();
-        static {
-            add(byte.class, Byte.class);
-            add(char.class, Character.class);
-            add(double.class, Double.class);
-            add(float.class, Float.class);
-            add(int.class, Integer.class);
-            add(long.class, Long.class);
-            add(short.class, Short.class);
-            add(boolean.class, Boolean.class);
-        }
-
-        private static void add(Class<?> primitiveClass, Class<?> wrapperClass) {
-            table.put(primitiveClass,
-                      new PrimitiveTypeInfo(primitiveClass, wrapperClass));
-        }
-
-        private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) {
-            assert primitiveClass.isPrimitive();
-
-            baseTypeString =
-                Array.newInstance(primitiveClass, 0)
-                .getClass().getName().substring(1);
-            wrapperClassName = dotToSlash(wrapperClass.getName());
-            wrapperValueOfDesc =
-                "(" + baseTypeString + ")L" + wrapperClassName + ";";
-            unwrapMethodName = primitiveClass.getName() + "Value";
-            unwrapMethodDesc = "()" + baseTypeString;
-        }
-
-        public static PrimitiveTypeInfo get(Class<?> cl) {
-            return table.get(cl);
-        }
-    }
-
-
-    /**
-     * A ConstantPool object represents the constant pool of a class file
-     * being generated.  This representation of a constant pool is designed
-     * specifically for use by ProxyGenerator; in particular, it assumes
-     * that constant pool entries will not need to be resorted (for example,
-     * by their type, as the Java compiler does), so that the final index
-     * value can be assigned and used when an entry is first created.
-     *
-     * Note that new entries cannot be created after the constant pool has
-     * been written to a class file.  To prevent such logic errors, a
-     * ConstantPool instance can be marked "read only", so that further
-     * attempts to add new entries will fail with a runtime exception.
-     *
-     * See JVMS section 4.4 for more information about the constant pool
-     * of a class file.
-     */
-    private static class ConstantPool {
-
-        /**
-         * list of constant pool entries, in constant pool index order.
-         *
-         * This list is used when writing the constant pool to a stream
-         * and for assigning the next index value.  Note that element 0
-         * of this list corresponds to constant pool index 1.
-         */
-        private List<Entry> pool = new ArrayList<>(32);
-
-        /**
-         * maps constant pool data of all types to constant pool indexes.
-         *
-         * This map is used to look up the index of an existing entry for
-         * values of all types.
-         */
-        private Map<Object,Short> map = new HashMap<>(16);
-
-        /** true if no new constant pool entries may be added */
-        private boolean readOnly = false;
-
-        /**
-         * Get or assign the index for a CONSTANT_Utf8 entry.
-         */
-        public short getUtf8(String s) {
-            if (s == null) {
-                throw new NullPointerException();
-            }
-            return getValue(s);
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_Integer entry.
-         */
-        public short getInteger(int i) {
-            return getValue(i);
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_Float entry.
-         */
-        public short getFloat(float f) {
-            return getValue(new Float(f));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_Class entry.
-         */
-        public short getClass(String name) {
-            short utf8Index = getUtf8(name);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_CLASS, utf8Index));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_String entry.
-         */
-        public short getString(String s) {
-            short utf8Index = getUtf8(s);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_STRING, utf8Index));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_FieldRef entry.
-         */
-        public short getFieldRef(String className,
-                                 String name, String descriptor)
-        {
-            short classIndex = getClass(className);
-            short nameAndTypeIndex = getNameAndType(name, descriptor);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_FIELD, classIndex, nameAndTypeIndex));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_MethodRef entry.
-         */
-        public short getMethodRef(String className,
-                                  String name, String descriptor)
-        {
-            short classIndex = getClass(className);
-            short nameAndTypeIndex = getNameAndType(name, descriptor);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_METHOD, classIndex, nameAndTypeIndex));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
-         */
-        public short getInterfaceMethodRef(String className, String name,
-                                           String descriptor)
-        {
-            short classIndex = getClass(className);
-            short nameAndTypeIndex = getNameAndType(name, descriptor);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
-        }
-
-        /**
-         * Get or assign the index for a CONSTANT_NameAndType entry.
-         */
-        public short getNameAndType(String name, String descriptor) {
-            short nameIndex = getUtf8(name);
-            short descriptorIndex = getUtf8(descriptor);
-            return getIndirect(new IndirectEntry(
-                CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
-        }
-
-        /**
-         * Set this ConstantPool instance to be "read only".
-         *
-         * After this method has been called, further requests to get
-         * an index for a non-existent entry will cause an InternalError
-         * to be thrown instead of creating of the entry.
-         */
-        public void setReadOnly() {
-            readOnly = true;
-        }
-
-        /**
-         * Write this constant pool to a stream as part of
-         * the class file format.
-         *
-         * This consists of writing the "constant_pool_count" and
-         * "constant_pool[]" items of the "ClassFile" structure, as
-         * described in JVMS section 4.1.
-         */
-        public void write(OutputStream out) throws IOException {
-            DataOutputStream dataOut = new DataOutputStream(out);
-
-            // constant_pool_count: number of entries plus one
-            dataOut.writeShort(pool.size() + 1);
-
-            for (Entry e : pool) {
-                e.write(dataOut);
-            }
-        }
-
-        /**
-         * Add a new constant pool entry and return its index.
-         */
-        private short addEntry(Entry entry) {
-            pool.add(entry);
-            /*
-             * Note that this way of determining the index of the
-             * added entry is wrong if this pool supports
-             * CONSTANT_Long or CONSTANT_Double entries.
-             */
-            if (pool.size() >= 65535) {
-                throw new IllegalArgumentException(
-                    "constant pool size limit exceeded");
-            }
-            return (short) pool.size();
-        }
-
-        /**
-         * Get or assign the index for an entry of a type that contains
-         * a direct value.  The type of the given object determines the
-         * type of the desired entry as follows:
-         *
-         *      java.lang.String        CONSTANT_Utf8
-         *      java.lang.Integer       CONSTANT_Integer
-         *      java.lang.Float         CONSTANT_Float
-         *      java.lang.Long          CONSTANT_Long
-         *      java.lang.Double        CONSTANT_DOUBLE
-         */
-        private short getValue(Object key) {
-            Short index = map.get(key);
-            if (index != null) {
-                return index.shortValue();
-            } else {
-                if (readOnly) {
-                    throw new InternalError(
-                        "late constant pool addition: " + key);
-                }
-                short i = addEntry(new ValueEntry(key));
-                map.put(key, i);
-                return i;
-            }
-        }
-
-        /**
-         * Get or assign the index for an entry of a type that contains
-         * references to other constant pool entries.
-         */
-        private short getIndirect(IndirectEntry e) {
-            Short index = map.get(e);
-            if (index != null) {
-                return index.shortValue();
-            } else {
-                if (readOnly) {
-                    throw new InternalError("late constant pool addition");
-                }
-                short i = addEntry(e);
-                map.put(e, i);
-                return i;
-            }
-        }
-
-        /**
-         * Entry is the abstact superclass of all constant pool entry types
-         * that can be stored in the "pool" list; its purpose is to define a
-         * common method for writing constant pool entries to a class file.
-         */
-        private abstract static class Entry {
-            public abstract void write(DataOutputStream out)
-                throws IOException;
-        }
-
-        /**
-         * ValueEntry represents a constant pool entry of a type that
-         * contains a direct value (see the comments for the "getValue"
-         * method for a list of such types).
-         *
-         * ValueEntry objects are not used as keys for their entries in the
-         * Map "map", so no useful hashCode or equals methods are defined.
-         */
-        private static class ValueEntry extends Entry {
-            private Object value;
-
-            public ValueEntry(Object value) {
-                this.value = value;
-            }
-
-            public void write(DataOutputStream out) throws IOException {
-                if (value instanceof String) {
-                    out.writeByte(CONSTANT_UTF8);
-                    out.writeUTF((String) value);
-                } else if (value instanceof Integer) {
-                    out.writeByte(CONSTANT_INTEGER);
-                    out.writeInt(((Integer) value).intValue());
-                } else if (value instanceof Float) {
-                    out.writeByte(CONSTANT_FLOAT);
-                    out.writeFloat(((Float) value).floatValue());
-                } else if (value instanceof Long) {
-                    out.writeByte(CONSTANT_LONG);
-                    out.writeLong(((Long) value).longValue());
-                } else if (value instanceof Double) {
-                    out.writeDouble(CONSTANT_DOUBLE);
-                    out.writeDouble(((Double) value).doubleValue());
-                } else {
-                    throw new InternalError("bogus value entry: " + value);
-                }
-            }
-        }
-
-        /**
-         * IndirectEntry represents a constant pool entry of a type that
-         * references other constant pool entries, i.e., the following types:
-         *
-         *      CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
-         *      CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
-         *      CONSTANT_NameAndType.
-         *
-         * Each of these entry types contains either one or two indexes of
-         * other constant pool entries.
-         *
-         * IndirectEntry objects are used as the keys for their entries in
-         * the Map "map", so the hashCode and equals methods are overridden
-         * to allow matching.
-         */
-        private static class IndirectEntry extends Entry {
-            private int tag;
-            private short index0;
-            private short index1;
-
-            /**
-             * Construct an IndirectEntry for a constant pool entry type
-             * that contains one index of another entry.
-             */
-            public IndirectEntry(int tag, short index) {
-                this.tag = tag;
-                this.index0 = index;
-                this.index1 = 0;
-            }
-
-            /**
-             * Construct an IndirectEntry for a constant pool entry type
-             * that contains two indexes for other entries.
-             */
-            public IndirectEntry(int tag, short index0, short index1) {
-                this.tag = tag;
-                this.index0 = index0;
-                this.index1 = index1;
-            }
-
-            public void write(DataOutputStream out) throws IOException {
-                out.writeByte(tag);
-                out.writeShort(index0);
-                /*
-                 * If this entry type contains two indexes, write
-                 * out the second, too.
-                 */
-                if (tag == CONSTANT_FIELD ||
-                    tag == CONSTANT_METHOD ||
-                    tag == CONSTANT_INTERFACEMETHOD ||
-                    tag == CONSTANT_NAMEANDTYPE)
-                {
-                    out.writeShort(index1);
-                }
-            }
-
-            public int hashCode() {
-                return tag + index0 + index1;
-            }
-
-            public boolean equals(Object obj) {
-                if (obj instanceof IndirectEntry) {
-                    IndirectEntry other = (IndirectEntry) obj;
-                    if (tag == other.tag &&
-                        index0 == other.index0 && index1 == other.index1)
-                    {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        }
-    }
-}
--- a/src/java.base/share/classes/sun/misc/Queue.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-/**
- * Queue: implements a simple queue mechanism.  Allows for enumeration of the
- * elements.
- *
- * @author Herb Jellinek
- */
-
-public class Queue<T> {
-
-    int length = 0;
-
-    QueueElement<T> head = null;
-    QueueElement<T> tail = null;
-
-    public Queue() {
-    }
-
-    /**
-     * Enqueue an object.
-     */
-    public synchronized void enqueue(T obj) {
-
-        QueueElement<T> newElt = new QueueElement<>(obj);
-
-        if (head == null) {
-            head = newElt;
-            tail = newElt;
-            length = 1;
-        } else {
-            newElt.next = head;
-            head.prev = newElt;
-            head = newElt;
-            length++;
-        }
-        notify();
-    }
-
-    /**
-     * Dequeue the oldest object on the queue.  Will wait indefinitely.
-     *
-     * @return    the oldest object on the queue.
-     * @exception java.lang.InterruptedException if any thread has
-     *              interrupted this thread.
-     */
-    public T dequeue() throws InterruptedException {
-        return dequeue(0L);
-    }
-
-    /**
-     * Dequeue the oldest object on the queue.
-     * @param timeOut the number of milliseconds to wait for something
-     * to arrive.
-     *
-     * @return    the oldest object on the queue.
-     * @exception java.lang.InterruptedException if any thread has
-     *              interrupted this thread.
-     */
-    public synchronized T dequeue(long timeOut)
-        throws InterruptedException {
-
-        while (tail == null) {
-            wait(timeOut);
-        }
-        QueueElement<T> elt = tail;
-        tail = elt.prev;
-        if (tail == null) {
-            head = null;
-        } else {
-            tail.next = null;
-        }
-        length--;
-        return elt.obj;
-    }
-
-    /**
-     * Is the queue empty?
-     * @return true if the queue is empty.
-     */
-    public synchronized boolean isEmpty() {
-        return (tail == null);
-    }
-
-    /**
-     * Returns an enumeration of the elements in Last-In, First-Out
-     * order. Use the Enumeration methods on the returned object to
-     * fetch the elements sequentially.
-     */
-    public final synchronized Enumeration<T> elements() {
-        return new LIFOQueueEnumerator<>(this);
-    }
-
-    /**
-     * Returns an enumeration of the elements in First-In, First-Out
-     * order. Use the Enumeration methods on the returned object to
-     * fetch the elements sequentially.
-     */
-    public final synchronized Enumeration<T> reverseElements() {
-        return new FIFOQueueEnumerator<>(this);
-    }
-
-    public synchronized void dump(String msg) {
-        System.err.println(">> "+msg);
-        System.err.println("["+length+" elt(s); head = "+
-                           (head == null ? "null" : (head.obj)+"")+
-                           " tail = "+(tail == null ? "null" : (tail.obj)+""));
-        QueueElement<T> cursor = head;
-        QueueElement<T> last = null;
-        while (cursor != null) {
-            System.err.println("  "+cursor);
-            last = cursor;
-            cursor = cursor.next;
-        }
-        if (last != tail) {
-            System.err.println("  tail != last: "+tail+", "+last);
-        }
-        System.err.println("]");
-    }
-}
-
-final class FIFOQueueEnumerator<T> implements Enumeration<T> {
-    Queue<T> queue;
-    QueueElement<T> cursor;
-
-    FIFOQueueEnumerator(Queue<T> q) {
-        queue = q;
-        cursor = q.tail;
-    }
-
-    public boolean hasMoreElements() {
-        return (cursor != null);
-    }
-
-    public T nextElement() {
-        synchronized (queue) {
-            if (cursor != null) {
-                QueueElement<T> result = cursor;
-                cursor = cursor.prev;
-                return result.obj;
-            }
-        }
-        throw new NoSuchElementException("FIFOQueueEnumerator");
-    }
-}
-
-final class LIFOQueueEnumerator<T> implements Enumeration<T> {
-    Queue<T> queue;
-    QueueElement<T> cursor;
-
-    LIFOQueueEnumerator(Queue<T> q) {
-        queue = q;
-        cursor = q.head;
-    }
-
-    public boolean hasMoreElements() {
-        return (cursor != null);
-    }
-
-    public T nextElement() {
-        synchronized (queue) {
-            if (cursor != null) {
-                QueueElement<T> result = cursor;
-                cursor = cursor.next;
-                return result.obj;
-            }
-        }
-        throw new NoSuchElementException("LIFOQueueEnumerator");
-    }
-}
-
-class QueueElement<T> {
-    QueueElement<T> next = null;
-    QueueElement<T> prev = null;
-
-    T obj = null;
-
-    QueueElement(T obj) {
-        this.obj = obj;
-    }
-
-    public String toString() {
-        return "QueueElement[obj="+obj+(prev == null ? " null" : " prev")+
-            (next == null ? " null" : " next")+"]";
-    }
-}
--- a/src/java.base/share/classes/sun/misc/Request.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * Requests are functor objects; that is, they provide part of the mechanism
- * for deferred function application.
- *
- * @author      Steven B. Byrne
- */
-
-public abstract class Request {
-    /**
-     * The main task of the Request object is to be exectuted from a request
-     * queue.
-     */
-    public abstract void execute();
-}
--- a/src/java.base/share/classes/sun/misc/RequestProcessor.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * The request processor allows functors (Request instances) to be created
- * in arbitrary threads, and to be posted for execution in a non-restricted
- * thread.
- *
- * @author      Steven B. Byrne
- */
-
-
-public class RequestProcessor implements Runnable {
-
-    private static Queue<Request> requestQueue;
-    private static Thread dispatcher;
-
-    /**
-     * Queues a Request instance for execution by the request procesor
-     * thread.
-     */
-    public static void postRequest(Request req) {
-        lazyInitialize();
-        requestQueue.enqueue(req);
-    }
-
-    /**
-     * Process requests as they are queued.
-     */
-    public void run() {
-        lazyInitialize();
-        while (true) {
-            try {
-                Request req = requestQueue.dequeue();
-                try {
-                    req.execute();
-                } catch (Throwable t) {
-                    // do nothing at the moment...maybe report an error
-                    // in the future
-                }
-            } catch (InterruptedException e) {
-                // do nothing at the present time.
-            }
-        }
-    }
-
-
-    /**
-     * This method initiates the request processor thread.  It is safe
-     * to call it after the thread has been started.  It provides a way for
-     * clients to deliberately control the context in which the request
-     * processor thread is created
-     */
-    public static synchronized void startProcessing() {
-        if (dispatcher == null) {
-            dispatcher = new ManagedLocalsThread(new RequestProcessor(), "Request Processor");
-            dispatcher.setPriority(Thread.NORM_PRIORITY + 2);
-            dispatcher.start();
-        }
-    }
-
-
-    /**
-     * This method performs lazy initialization.
-     */
-    private static synchronized void lazyInitialize() {
-        if (requestQueue == null) {
-            requestQueue = new Queue<Request>();
-        }
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/Signal.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/misc/Signal.java	Tue Dec 22 13:41:12 2015 -0800
@@ -213,7 +213,7 @@
             }
         };
         if (handler != null) {
-            new ManagedLocalsThread(runnable, sig + " handler").start();
+            new Thread(null, runnable, sig + " handler", 0, false).start();
         }
     }
 
--- a/src/java.base/share/classes/sun/misc/UCDecoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PushbackInputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a robust character decoder. The decoder will
- * converted encoded text into binary data.
- *
- * The basic encoding unit is a 3 character atom. It encodes two bytes
- * of data. Bytes are encoded into a 64 character set, the characters
- * were chosen specifically because they appear in all codesets.
- * We don't care what their numerical equivalent is because
- * we use a character array to map them. This is like UUencoding
- * with the dependency on ASCII removed.
- *
- * The three chars that make up an atom are encoded as follows:
- * <pre>
- *      00xxxyyy 00axxxxx 00byyyyy
- *      00 = leading zeros, all values are 0 - 63
- *      xxxyyy - Top 3 bits of X, Top 3 bits of Y
- *      axxxxx - a = X parity bit, xxxxx lower 5 bits of X
- *      byyyyy - b = Y parity bit, yyyyy lower 5 bits of Y
- * </pre>
- *
- * The atoms are arranged into lines suitable for inclusion into an
- * email message or text file. The number of bytes that are encoded
- * per line is 48 which keeps the total line length  under 80 chars)
- *
- * Each line has the form(
- * <pre>
- *  *(LLSS)(DDDD)(DDDD)(DDDD)...(CRC)
- *  Where each (xxx) represents a three character atom.
- *  (LLSS) - 8 bit length (high byte), and sequence number
- *           modulo 256;
- *  (DDDD) - Data byte atoms, if length is odd, last data
- *           atom has (DD00) (high byte data, low byte 0)
- *  (CRC)  - 16 bit CRC for the line, includes length,
- *           sequence, and all data bytes. If there is a
- *           zero pad byte (odd length) it is _NOT_
- *           included in the CRC.
- * </pre>
- *
- * If an error is encountered during decoding this class throws a
- * CEFormatException. The specific detail messages are:
- *
- * <pre>
- *    "UCDecoder: High byte parity error."
- *    "UCDecoder: Low byte parity error."
- *    "UCDecoder: Out of sequence line."
- *    "UCDecoder: CRC check failed."
- * </pre>
- *
- * @author      Chuck McManis
- * @see         CharacterEncoder
- * @see         UCEncoder
- */
-public class UCDecoder extends CharacterDecoder {
-
-    /** This class encodes two bytes per atom. */
-    protected int bytesPerAtom() {
-        return (2);
-    }
-
-    /** this class encodes 48 bytes per line */
-    protected int bytesPerLine() {
-        return (48);
-    }
-
-    /* this is the UCE mapping of 0-63 to characters .. */
-    private static final byte map_array[] = {
-        //     0         1         2         3         4         5         6         7
-        (byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7', // 0
-        (byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F', // 1
-        (byte)'G',(byte)'H',(byte)'I',(byte)'J',(byte)'K',(byte)'L',(byte)'M',(byte)'N', // 2
-        (byte)'O',(byte)'P',(byte)'Q',(byte)'R',(byte)'S',(byte)'T',(byte)'U',(byte)'V', // 3
-        (byte)'W',(byte)'X',(byte)'Y',(byte)'Z',(byte)'a',(byte)'b',(byte)'c',(byte)'d', // 4
-        (byte)'e',(byte)'f',(byte)'g',(byte)'h',(byte)'i',(byte)'j',(byte)'k',(byte)'l', // 5
-        (byte)'m',(byte)'n',(byte)'o',(byte)'p',(byte)'q',(byte)'r',(byte)'s',(byte)'t', // 6
-        (byte)'u',(byte)'v',(byte)'w',(byte)'x',(byte)'y',(byte)'z',(byte)'(',(byte)')'  // 7
-    };
-
-    private int sequence;
-    private byte tmp[] = new byte[2];
-    private CRC16 crc = new CRC16();
-
-    /**
-     * Decode one atom - reads the characters from the input stream, decodes
-     * them, and checks for valid parity.
-     */
-    protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int l) throws IOException {
-        int i, p1, p2, np1, np2;
-        byte a = -1, b = -1, c = -1;
-        byte high_byte, low_byte;
-        byte tmp[] = new byte[3];
-
-        i = inStream.read(tmp);
-        if (i != 3) {
-                throw new CEStreamExhausted();
-        }
-        for (i = 0; (i < 64) && ((a == -1) || (b == -1) || (c == -1)); i++) {
-            if (tmp[0] == map_array[i]) {
-                a = (byte) i;
-            }
-            if (tmp[1] == map_array[i]) {
-                b = (byte) i;
-            }
-            if (tmp[2] == map_array[i]) {
-                c = (byte) i;
-            }
-        }
-        high_byte = (byte) (((a & 0x38) << 2) + (b & 0x1f));
-        low_byte = (byte) (((a & 0x7) << 5) + (c & 0x1f));
-        p1 = 0;
-        p2 = 0;
-        for (i = 1; i < 256; i = i * 2) {
-            if ((high_byte & i) != 0)
-                p1++;
-            if ((low_byte & i) != 0)
-                p2++;
-        }
-        np1 = (b & 32) / 32;
-        np2 = (c & 32) / 32;
-        if ((p1 & 1) != np1) {
-            throw new CEFormatException("UCDecoder: High byte parity error.");
-        }
-        if ((p2 & 1) != np2) {
-            throw new CEFormatException("UCDecoder: Low byte parity error.");
-        }
-        outStream.write(high_byte);
-        crc.update(high_byte);
-        if (l == 2) {
-            outStream.write(low_byte);
-            crc.update(low_byte);
-        }
-    }
-
-    private ByteArrayOutputStream lineAndSeq = new ByteArrayOutputStream(2);
-
-    /**
-     * decodeBufferPrefix initializes the sequence number to zero.
-     */
-    protected void decodeBufferPrefix(PushbackInputStream inStream, OutputStream outStream) {
-        sequence = 0;
-    }
-
-    /**
-     * decodeLinePrefix reads the sequence number and the number of
-     * encoded bytes from the line. If the sequence number is not the
-     * previous sequence number + 1 then an exception is thrown.
-     * UCE lines are line terminator immune, they all start with *
-     * so the other thing this method does is scan for the next line
-     * by looking for the * character.
-     *
-     * @exception CEFormatException out of sequence lines detected.
-     */
-    protected int decodeLinePrefix(PushbackInputStream inStream, OutputStream outStream)  throws IOException {
-        int     i;
-        int     nLen, nSeq;
-        byte    xtmp[];
-        int     c;
-
-        crc.value = 0;
-        while (true) {
-            c = inStream.read(tmp, 0, 1);
-            if (c == -1) {
-                throw new CEStreamExhausted();
-            }
-            if (tmp[0] == '*') {
-                break;
-            }
-        }
-        lineAndSeq.reset();
-        decodeAtom(inStream, lineAndSeq, 2);
-        xtmp = lineAndSeq.toByteArray();
-        nLen = xtmp[0] & 0xff;
-        nSeq = xtmp[1] & 0xff;
-        if (nSeq != sequence) {
-            throw new CEFormatException("UCDecoder: Out of sequence line.");
-        }
-        sequence = (sequence + 1) & 0xff;
-        return (nLen);
-    }
-
-
-    /**
-     * this method reads the CRC that is at the end of every line and
-     * verifies that it matches the computed CRC.
-     *
-     * @exception CEFormatException if CRC check fails.
-     */
-    protected void decodeLineSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
-        int i;
-        int lineCRC = crc.value;
-        int readCRC;
-        byte tmp[];
-
-        lineAndSeq.reset();
-        decodeAtom(inStream, lineAndSeq, 2);
-        tmp = lineAndSeq.toByteArray();
-        readCRC = ((tmp[0] << 8) & 0xFF00) + (tmp[1] & 0xff);
-        if (readCRC != lineCRC) {
-            throw new CEFormatException("UCDecoder: CRC check failed.");
-        }
-    }
-}
--- a/src/java.base/share/classes/sun/misc/UCEncoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a robust character encoder. The encoder is designed
- * to convert binary data into printable characters. The characters are
- * assumed to exist but they are not assumed to be ASCII, the complete set
- * is 0-9, A-Z, a-z, "(", and ")".
- *
- * The basic encoding unit is a 3 character atom. It encodes two bytes
- * of data. Bytes are encoded into a 64 character set, the characters
- * were chosen specifically because they appear in all codesets.
- * We don't care what their numerical equivalent is because
- * we use a character array to map them. This is like UUencoding
- * with the dependency on ASCII removed.
- *
- * The three chars that make up an atom are encoded as follows:
- * <pre>
- *      00xxxyyy 00axxxxx 00byyyyy
- *      00 = leading zeros, all values are 0 - 63
- *      xxxyyy - Top 3 bits of X, Top 3 bits of Y
- *      axxxxx - a = X parity bit, xxxxx lower 5 bits of X
- *      byyyyy - b = Y parity bit, yyyyy lower 5 bits of Y
- * </pre>
- *
- * The atoms are arranged into lines suitable for inclusion into an
- * email message or text file. The number of bytes that are encoded
- * per line is 48 which keeps the total line length  under 80 chars)
- *
- * Each line has the form(
- * <pre>
- *  *(LLSS)(DDDD)(DDDD)(DDDD)...(CRC)
- *  Where each (xxx) represents a three character atom.
- *  (LLSS) - 8 bit length (high byte), and sequence number
- *           modulo 256;
- *  (DDDD) - Data byte atoms, if length is odd, last data
- *           atom has (DD00) (high byte data, low byte 0)
- *  (CRC)  - 16 bit CRC for the line, includes length,
- *           sequence, and all data bytes. If there is a
- *           zero pad byte (odd length) it is _NOT_
- *           included in the CRC.
- * </pre>
- *
- * @author      Chuck McManis
- * @see         CharacterEncoder
- * @see         UCDecoder
- */
-public class UCEncoder extends CharacterEncoder {
-
-    /** this clase encodes two bytes per atom */
-    protected int bytesPerAtom() {
-        return (2);
-    }
-
-    /** this class encodes 48 bytes per line */
-    protected int bytesPerLine() {
-        return (48);
-    }
-
-    /* this is the UCE mapping of 0-63 to characters .. */
-    private static final byte map_array[] = {
-        //     0         1         2         3         4         5         6         7
-        (byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7', // 0
-        (byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F', // 1
-        (byte)'G',(byte)'H',(byte)'I',(byte)'J',(byte)'K',(byte)'L',(byte)'M',(byte)'N', // 2
-        (byte)'O',(byte)'P',(byte)'Q',(byte)'R',(byte)'S',(byte)'T',(byte)'U',(byte)'V', // 3
-        (byte)'W',(byte)'X',(byte)'Y',(byte)'Z',(byte)'a',(byte)'b',(byte)'c',(byte)'d', // 4
-        (byte)'e',(byte)'f',(byte)'g',(byte)'h',(byte)'i',(byte)'j',(byte)'k',(byte)'l', // 5
-        (byte)'m',(byte)'n',(byte)'o',(byte)'p',(byte)'q',(byte)'r',(byte)'s',(byte)'t', // 6
-        (byte)'u',(byte)'v',(byte)'w',(byte)'x',(byte)'y',(byte)'z',(byte)'(',(byte)')'  // 7
-    };
-
-    private int sequence;
-    private byte tmp[] = new byte[2];
-    private CRC16 crc = new CRC16();
-
-    /**
-     * encodeAtom - take two bytes and encode them into the correct
-     * three characters. If only one byte is to be encoded, the other
-     * must be zero. The padding byte is not included in the CRC computation.
-     */
-    protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len) throws IOException
-    {
-        int     i;
-        int     p1, p2; // parity bits
-        byte    a, b;
-
-        a = data[offset];
-        if (len == 2) {
-            b = data[offset+1];
-        } else {
-            b = 0;
-        }
-        crc.update(a);
-        if (len == 2) {
-            crc.update(b);
-        }
-        outStream.write(map_array[((a >>> 2) & 0x38) + ((b >>> 5) & 0x7)]);
-        p1 = 0; p2 = 0;
-        for (i = 1; i < 256; i = i * 2) {
-            if ((a & i) != 0) {
-                p1++;
-            }
-            if ((b & i) != 0) {
-                p2++;
-            }
-        }
-        p1 = (p1 & 1) * 32;
-        p2 = (p2 & 1) * 32;
-        outStream.write(map_array[(a & 31) + p1]);
-        outStream.write(map_array[(b & 31) + p2]);
-        return;
-    }
-
-    /**
-     * Each UCE encoded line starts with a prefix of '*[XXX]', where
-     * the sequence number and the length are encoded in the first
-     * atom.
-     */
-    protected void encodeLinePrefix(OutputStream outStream, int length) throws IOException {
-        outStream.write('*');
-        crc.value = 0;
-        tmp[0] = (byte) length;
-        tmp[1] = (byte) sequence;
-        sequence = (sequence + 1) & 0xff;
-        encodeAtom(outStream, tmp, 0, 2);
-    }
-
-
-    /**
-     * each UCE encoded line ends with YYY and encoded version of the
-     * 16 bit checksum. The most significant byte of the check sum
-     * is always encoded FIRST.
-     */
-    protected void encodeLineSuffix(OutputStream outStream) throws IOException {
-        tmp[0] = (byte) ((crc.value >>> 8) & 0xff);
-        tmp[1] = (byte) (crc.value & 0xff);
-        encodeAtom(outStream, tmp, 0, 2);
-        super.pStream.println();
-    }
-
-    /**
-     * The buffer prefix code is used to initialize the sequence number
-     * to zero.
-     */
-    protected void encodeBufferPrefix(OutputStream a) throws IOException {
-        sequence = 0;
-        super.encodeBufferPrefix(a);
-    }
-}
--- a/src/java.base/share/classes/sun/misc/UUDecoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 1995, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.PushbackInputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a Berkeley uu character decoder. This decoder
- * was made famous by the uudecode program.
- *
- * The basic character coding is algorithmic, taking 6 bits of binary
- * data and adding it to an ASCII ' ' (space) character. This converts
- * these six bits into a printable representation. Note that it depends
- * on the ASCII character encoding standard for english. Groups of three
- * bytes are converted into 4 characters by treating the three bytes
- * a four 6 bit groups, group 1 is byte 1's most significant six bits,
- * group 2 is byte 1's least significant two bits plus byte 2's four
- * most significant bits. etc.
- *
- * In this encoding, the buffer prefix is:
- * <pre>
- *     begin [mode] [filename]
- * </pre>
- *
- * This is followed by one or more lines of the form:
- * <pre>
- *      (len)(data)(data)(data) ...
- * </pre>
- * where (len) is the number of bytes on this line. Note that groupings
- * are always four characters, even if length is not a multiple of three
- * bytes. When less than three characters are encoded, the values of the
- * last remaining bytes is undefined and should be ignored.
- *
- * The last line of data in a uuencoded buffer is represented by a single
- * space character. This is translated by the decoding engine to a line
- * length of zero. This is immediately followed by a line which contains
- * the word 'end[newline]'
- *
- * If an error is encountered during decoding this class throws a
- * CEFormatException. The specific detail messages are:
- *
- * <pre>
- *      "UUDecoder: No begin line."
- *      "UUDecoder: Malformed begin line."
- *      "UUDecoder: Short Buffer."
- *      "UUDecoder: Bad Line Length."
- *      "UUDecoder: Missing 'end' line."
- * </pre>
- *
- * @author      Chuck McManis
- * @see         CharacterDecoder
- * @see         UUEncoder
- */
-public class UUDecoder extends CharacterDecoder {
-
-    /**
-     * This string contains the name that was in the buffer being decoded.
-     */
-    public String bufferName;
-
-    /**
-     * Represents UNIX(tm) mode bits. Generally three octal digits
-     * representing read, write, and execute permission of the owner,
-     * group owner, and  others. They should be interpreted as the bit groups:
-     * <pre>
-     * (owner) (group) (others)
-     *  rwx      rwx     rwx    (r = read, w = write, x = execute)
-     *</pre>
-     *
-     */
-    public int mode;
-
-
-    /**
-     * UU encoding specifies 3 bytes per atom.
-     */
-    protected int bytesPerAtom() {
-        return (3);
-    }
-
-    /**
-     * All UU lines have 45 bytes on them, for line length of 15*4+1 or 61
-     * characters per line.
-     */
-    protected int bytesPerLine() {
-        return (45);
-    }
-
-    /** This is used to decode the atoms */
-    private byte decoderBuffer[] = new byte[4];
-
-    /**
-     * Decode a UU atom. Note that if l is less than 3 we don't write
-     * the extra bits, however the encoder always encodes 4 character
-     * groups even when they are not needed.
-     */
-    protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int l)
-        throws IOException {
-        int i, c1, c2, c3, c4;
-        int a, b, c;
-        StringBuilder x = new StringBuilder();
-
-        for (i = 0; i < 4; i++) {
-            c1 = inStream.read();
-            if (c1 == -1) {
-                throw new CEStreamExhausted();
-            }
-            x.append((char)c1);
-            decoderBuffer[i] = (byte) ((c1 - ' ') & 0x3f);
-        }
-        a = ((decoderBuffer[0] << 2) & 0xfc) | ((decoderBuffer[1] >>> 4) & 3);
-        b = ((decoderBuffer[1] << 4) & 0xf0) | ((decoderBuffer[2] >>> 2) & 0xf);
-        c = ((decoderBuffer[2] << 6) & 0xc0) | (decoderBuffer[3] & 0x3f);
-        outStream.write((byte)(a & 0xff));
-        if (l > 1) {
-            outStream.write((byte)( b & 0xff));
-        }
-        if (l > 2) {
-            outStream.write((byte)(c&0xff));
-        }
-    }
-
-    /**
-     * For uuencoded buffers, the data begins with a line of the form:
-     *          begin MODE FILENAME
-     * This line always starts in column 1.
-     */
-    protected void decodeBufferPrefix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
-        int     c;
-        StringBuilder q = new StringBuilder(32);
-        String r;
-        boolean sawNewLine;
-
-        /*
-         * This works by ripping through the buffer until it finds a 'begin'
-         * line or the end of the buffer.
-         */
-        sawNewLine = true;
-        while (true) {
-            c = inStream.read();
-            if (c == -1) {
-                throw new CEFormatException("UUDecoder: No begin line.");
-            }
-            if ((c == 'b')  && sawNewLine){
-                c = inStream.read();
-                if (c == 'e') {
-                    break;
-                }
-            }
-            sawNewLine = (c == '\n') || (c == '\r');
-        }
-
-        /*
-         * Now we think its begin, (we've seen ^be) so verify it here.
-         */
-        while ((c != '\n') && (c != '\r')) {
-            c = inStream.read();
-            if (c == -1) {
-                throw new CEFormatException("UUDecoder: No begin line.");
-            }
-            if ((c != '\n') && (c != '\r')) {
-                q.append((char)c);
-            }
-        }
-        r = q.toString();
-        if (r.indexOf(' ') != 3) {
-                throw new CEFormatException("UUDecoder: Malformed begin line.");
-        }
-        mode = Integer.parseInt(r.substring(4,7));
-        bufferName = r.substring(r.indexOf(' ',6)+1);
-        /*
-         * Check for \n after \r
-         */
-        if (c == '\r') {
-            c = inStream.read ();
-            if ((c != '\n') && (c != -1))
-                inStream.unread (c);
-        }
-    }
-
-    /**
-     * In uuencoded buffers, encoded lines start with a character that
-     * represents the number of bytes encoded in this line. The last
-     * line of input is always a line that starts with a single space
-     * character, which would be a zero length line.
-     */
-    protected int decodeLinePrefix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
-        int     c;
-
-        c = inStream.read();
-        if (c == ' ') {
-            c = inStream.read(); /* discard the (first)trailing CR or LF  */
-            c = inStream.read(); /* check for a second one  */
-            if ((c != '\n') && (c != -1))
-                inStream.unread (c);
-            throw new CEStreamExhausted();
-        } else if (c == -1) {
-            throw new CEFormatException("UUDecoder: Short Buffer.");
-        }
-
-        c = (c - ' ') & 0x3f;
-        if (c > bytesPerLine()) {
-            throw new CEFormatException("UUDecoder: Bad Line Length.");
-        }
-        return (c);
-    }
-
-
-    /**
-     * Find the end of the line for the next operation.
-     * The following sequences are recognized as end-of-line
-     * CR, CR LF, or LF
-     */
-    protected void decodeLineSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
-        int c;
-        while (true) {
-            c = inStream.read();
-            if (c == -1) {
-                throw new CEStreamExhausted();
-            }
-            if (c == '\n') {
-                break;
-            }
-            if (c == '\r') {
-                c = inStream.read();
-                if ((c != '\n') && (c != -1)) {
-                    inStream.unread (c);
-                }
-                break;
-            }
-        }
-    }
-
-    /**
-     * UUencoded files have a buffer suffix which consists of the word
-     * end. This line should immediately follow the line with a single
-     * space in it.
-     */
-    protected void decodeBufferSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException  {
-        int     c;
-
-        c = inStream.read(decoderBuffer);
-        if ((decoderBuffer[0] != 'e') || (decoderBuffer[1] != 'n') ||
-            (decoderBuffer[2] != 'd')) {
-            throw new CEFormatException("UUDecoder: Missing 'end' line.");
-        }
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/UUEncoder.java	Fri Dec 18 10:00:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a Berkeley uu character encoder. This encoder
- * was made famous by uuencode program.
- *
- * The basic character coding is algorithmic, taking 6 bits of binary
- * data and adding it to an ASCII ' ' (space) character. This converts
- * these six bits into a printable representation. Note that it depends
- * on the ASCII character encoding standard for english. Groups of three
- * bytes are converted into 4 characters by treating the three bytes
- * a four 6 bit groups, group 1 is byte 1's most significant six bits,
- * group 2 is byte 1's least significant two bits plus byte 2's four
- * most significant bits. etc.
- *
- * In this encoding, the buffer prefix is:
- * <pre>
- *     begin [mode] [filename]
- * </pre>
- *
- * This is followed by one or more lines of the form:
- * <pre>
- *      (len)(data)(data)(data) ...
- * </pre>
- * where (len) is the number of bytes on this line. Note that groupings
- * are always four characters, even if length is not a multiple of three
- * bytes. When less than three characters are encoded, the values of the
- * last remaining bytes is undefined and should be ignored.
- *
- * The last line of data in a uuencoded file is represented by a single
- * space character. This is translated by the decoding engine to a line
- * length of zero. This is immediately followed by a line which contains
- * the word 'end[newline]'
- *
- * @author      Chuck McManis
- * @see         CharacterEncoder
- * @see         UUDecoder
- */
-public class UUEncoder extends CharacterEncoder {
-
-    /**
-     * This name is stored in the begin line.
-     */
-    private String bufferName;
-
-    /**
-     * Represents UNIX(tm) mode bits. Generally three octal digits representing
-     * read, write, and execute permission of the owner, group owner, and
-     * others. They should be interpreted as the bit groups:
-     * (owner) (group) (others)
-     *  rwx      rwx     rwx    (r = read, w = write, x = execute)
-     *
-     * By default these are set to 644 (UNIX rw-r--r-- permissions).
-     */
-    private int mode;
-
-
-    /**
-     * Default - buffer begin line will be:
-     * <pre>
-     *  begin 644 encoder.buf
-     * </pre>
-     */
-    public UUEncoder() {
-        bufferName = "encoder.buf";
-        mode = 644;
-    }
-
-    /**
-     * Specifies a name for the encoded buffer, begin line will be:
-     * <pre>
-     *  begin 644 [FNAME]
-     * </pre>
-     */
-    public UUEncoder(String fname) {
-        bufferName = fname;
-        mode = 644;
-    }
-
-    /**
-     * Specifies a name and mode for the encoded buffer, begin line will be:
-     * <pre>
-     *  begin [MODE] [FNAME]
-     * </pre>
-     */
-    public UUEncoder(String fname, int newMode) {
-        bufferName = fname;
-        mode = newMode;
-    }
-
-    /** number of bytes per atom in uuencoding is 3 */
-    protected int bytesPerAtom() {
-        return (3);
-    }
-
-    /** number of bytes per line in uuencoding is 45 */
-    protected int bytesPerLine() {
-        return (45);
-    }
-
-    /**
-     * encodeAtom - take three bytes and encodes them into 4 characters
-     * If len is less than 3 then remaining bytes are filled with '1'.
-     * This insures that the last line won't end in spaces and potentiallly
-     * be truncated.
-     */
-    protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len)
-        throws IOException {
-        byte    a, b = 1, c = 1;
-        int     c1, c2, c3, c4;
-
-        a = data[offset];
-        if (len > 1) {
-            b = data[offset+1];
-        }
-        if (len > 2) {
-            c = data[offset+2];
-        }
-
-        c1 = (a >>> 2) & 0x3f;
-        c2 = ((a << 4) & 0x30) | ((b >>> 4) & 0xf);
-        c3 = ((b << 2) & 0x3c) | ((c >>> 6) & 0x3);
-        c4 = c & 0x3f;
-        outStream.write(c1 + ' ');
-        outStream.write(c2 + ' ');
-        outStream.write(c3 + ' ');
-        outStream.write(c4 + ' ');
-        return;
-    }
-
-    /**
-     * Encode the line prefix which consists of the single character. The
-     * lenght is added to the value of ' ' (32 decimal) and printed.
-     */
-    protected void encodeLinePrefix(OutputStream outStream, int length)
-        throws IOException {
-        outStream.write((length & 0x3f) + ' ');
-    }
-
-
-    /**
-     * The line suffix for uuencoded files is simply a new line.
-     */
-    protected void encodeLineSuffix(OutputStream outStream) throws IOException {
-        pStream.println();
-    }
-
-    /**
-     * encodeBufferPrefix writes the begin line to the output stream.
-     */
-    protected void encodeBufferPrefix(OutputStream a) throws IOException {
-        super.pStream = new PrintStream(a);
-        super.pStream.print("begin "+mode+" ");
-        if (bufferName != null) {
-            super.pStream.println(bufferName);
-        } else {
-            super.pStream.println("encoder.bin");
-        }
-        super.pStream.flush();
-    }
-
-    /**
-     * encodeBufferSuffix writes the single line containing space (' ') and
-     * the line containing the word 'end' to the output stream.
-     */
-    protected void encodeBufferSuffix(OutputStream a) throws IOException {
-        super.pStream.println(" \nend");
-        super.pStream.flush();
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/VM.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/misc/VM.java	Tue Dec 22 13:41:12 2015 -0800
@@ -274,9 +274,6 @@
         // used by java.lang.Integer.IntegerCache
         props.remove("java.lang.Integer.IntegerCache.high");
 
-        // used by java.util.zip.ZipFile
-        props.remove("sun.zip.disableMemoryMapping");
-
         // used by sun.launcher.LauncherHelper
         props.remove("sun.java.launcher.diag");
     }
--- a/src/java.base/share/classes/sun/net/NetworkServer.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/net/NetworkServer.java	Tue Dec 22 13:41:12 2015 -0800
@@ -27,7 +27,6 @@
 import java.io.*;
 import java.net.Socket;
 import java.net.ServerSocket;
-import sun.misc.ManagedLocalsThread;
 
 /**
  * This is the base class for network servers.  To define a new type
@@ -73,7 +72,7 @@
                     NetworkServer n = (NetworkServer)clone();
                     n.serverSocket = null;
                     n.clientSocket = ns;
-                    new ManagedLocalsThread(n).start();
+                    new Thread(null, n, "NetworkServer", 0, false).start();
                 } catch(Exception e) {
                     System.out.print("Server failure\n");
                     e.printStackTrace();
@@ -108,7 +107,7 @@
         for each new connection. */
     public final void startServer(int port) throws IOException {
         serverSocket = new ServerSocket(port, 50);
-        serverInstance = new ManagedLocalsThread(this);
+        serverInstance = new Thread(null, this, "NetworkServer", 0, false);
         serverInstance.start();
     }
 
--- a/src/java.base/share/classes/sun/net/www/MimeLauncher.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/net/www/MimeLauncher.java	Tue Dec 22 13:41:12 2015 -0800
@@ -27,9 +27,8 @@
 import java.net.URL;
 import java.io.*;
 import java.util.StringTokenizer;
-import sun.misc.ManagedLocalsThread;
 
-class MimeLauncher extends ManagedLocalsThread {
+class MimeLauncher extends Thread {
     java.net.URLConnection uc;
     MimeEntry m;
     String genericTempFileTemplate;
@@ -38,7 +37,7 @@
 
     MimeLauncher (MimeEntry M, java.net.URLConnection uc,
                   InputStream is, String tempFileTemplate, String threadName) throws ApplicationLaunchException {
-        super(threadName);
+        super(null, null, threadName, 0, false);
         m = M;
         this.uc = uc;
         this.is = is;
--- a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java	Tue Dec 22 13:41:12 2015 -0800
@@ -30,7 +30,6 @@
 import java.security.PrivilegedAction;
 import java.io.IOException;
 import java.util.*;
-import sun.misc.ManagedLocalsThread;
 
 /**
  * Base implementation of background poller thread used in watch service
@@ -60,7 +59,7 @@
         AccessController.doPrivileged(new PrivilegedAction<>() {
             @Override
             public Object run() {
-                Thread thr = new ManagedLocalsThread(thisRunnable);
+                Thread thr = new Thread(null, thisRunnable, "FileSystemWatchService", 0, false);
                 thr.setDaemon(true);
                 thr.start();
                 return null;
--- a/src/java.base/share/classes/sun/nio/fs/Cancellable.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/nio/fs/Cancellable.java	Tue Dec 22 13:41:12 2015 -0800
@@ -25,7 +25,6 @@
 
 package sun.nio.fs;
 
-import sun.misc.ManagedLocalsThread;
 import jdk.internal.misc.Unsafe;
 import java.util.concurrent.ExecutionException;
 
@@ -118,7 +117,7 @@
      * thread by writing into the memory location that it polls cooperatively.
      */
     static void runInterruptibly(Cancellable task) throws ExecutionException {
-        Thread t = new ManagedLocalsThread(task);
+        Thread t = new Thread(null, task, "NIO-Task", 0, false);
         t.start();
         boolean cancelledByInterrupt = false;
         while (t.isAlive()) {
--- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java	Tue Dec 22 13:41:12 2015 -0800
@@ -35,7 +35,6 @@
 import java.util.*;
 import java.util.concurrent.*;
 import com.sun.nio.file.SensitivityWatchEventModifier;
-import sun.misc.ManagedLocalsThread;
 
 /**
  * Simple WatchService implementation that uses periodic tasks to poll
@@ -59,7 +58,7 @@
             .newSingleThreadScheduledExecutor(new ThreadFactory() {
                  @Override
                  public Thread newThread(Runnable r) {
-                     Thread t = new ManagedLocalsThread(r);
+                     Thread t = new Thread(null, r, "FileSystemWatchService", 0, false);
                      t.setDaemon(true);
                      return t;
                  }});
--- a/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java	Fri Dec 18 10:00:55 2015 -0800
+++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java	Tue Dec 22 13:41:12 2015 -0800
@@ -62,7 +62,7 @@
                     decl);
         if (type instanceof Class) {
             return new AnnotatedTypeBaseImpl(type,
-                    addNesting(type, currentLoc),
+                    currentLoc,
                     actualTypeAnnos,
                     allOnSameTarget,
                     decl);
@@ -74,7 +74,7 @@
                     decl);
         } else if (type instanceof ParameterizedType) {
             return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
-                    addNesting(type, currentLoc),
+                    currentLoc,
                     actualTypeAnnos,
                     allOnSameTarget,
                     decl);
@@ -88,7 +88,7 @@
         throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
     }
 
-    private static LocationInfo addNesting(Type type, LocationInfo addTo) {
+    public static LocationInfo nestingForType(Type type, LocationInfo addTo) {
         if (isArray(type))
             return addTo;
         if (type instanceof Class) {
@@ -96,13 +96,13 @@
             if (clz.getEnclosingClass() == null)
                 return addTo;
             if (Modifier.isStatic(clz.getModifiers()))
-                return addNesting(clz.getEnclosingClass(), addTo);
-            return addNesting(clz.getEnclosingClass(), addTo.pushInner());
+                return nestingForType(clz.getEnclosingClass(), addTo);
+            return nestingForType(clz.getEnclosingClass(), addTo.pushInner());
         } else if (type instanceof ParameterizedType) {
             ParameterizedType t = (ParameterizedType)type;
             if (t.getOwnerType() == null)
                 return addTo;
-            return addNesting(t.getOwnerType(), addTo.pushInner());
+            return nestingForType(t.getOwnerType(), addTo.pushInner());
         }
         return addTo;
     }
@@ -118,8 +118,9 @@
         return false;
     }
 
+    static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
     static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
-                                                            new TypeAnnotation[0], new TypeAnnotation[0], null);
+            EMPTY_TYPE_ANNOTATION_ARRAY, EMPTY_TYPE_ANNOTATION_ARRAY, null);
     static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
 
     private static class AnnotatedTypeBaseImpl implements AnnotatedType {
@@ -177,6 +178,30 @@
             return type;
         }
 
+        @Override
+        public AnnotatedType getAnnotatedOwnerType() {
+            if (!(type instanceof Class<?>))
+                throw new IllegalStateException("Can't compute owner");
+
+            Class<?> inner = (Class<?>)type;
+            Class<?> owner = inner.getDeclaringClass();
+            if (owner == null) // top-level, local or anonymous
+                return null;
+            if (inner.isPrimitive() || inner == Void.TYPE)
+                return null;
+
+            LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
+            TypeAnnotation[]all = getTypeAnnotations();
+            List<TypeAnnotation> l = new ArrayList<>(all.length);
+
+            for (TypeAnnotation t : all)
+                if (t.getLocationInfo().isSameLocationInfo(outerLoc))
+                    l.add(t);
+
+            return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
+
+        }
+
         // Implementation details
         final LocationInfo getLocation() {
             return location;
@@ -198,11 +223,17 @@
 
         @Override
         public AnnotatedType getAnnotatedGenericComponentType() {
-            return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(),
-                                                           getLocation().pushArray(),
-                                                           getTypeAnnotations(),
-                                                           getTypeAnnotations(),
-                                                           getDecl());
+            Type t = getComponentType();
+            return AnnotatedTypeFactory.buildAnnotatedType(t,
+                    nestingForType(t, getLocation().pushArray()),
+                    getTypeAnnotations(),
+                    getTypeAnnotations(),
+                    getDecl());
+        }
+
+        @Override
+        public AnnotatedType getAnnotatedOwnerType() {
+            return null;
         }
 
         private Type getComponentType() {
@@ -227,6 +258,11 @@
             return getTypeVariable().getAnnotatedBounds();
         }
 
+        @Override
+        public AnnotatedType getAnnotatedOwnerType() {
+            return null;
+        }
+
         private TypeVariable<?> getTypeVariable() {
             return (TypeVariable)getType();
         }
@@ -248,19 +284,35 @@
             int initialCapacity = getTypeAnnotations().length;
             for (int i = 0; i < res.length; i++) {
                 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
-                LocationInfo newLoc = getLocation().pushTypeArg((byte)i);
+                LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
                 for (TypeAnnotation t : getTypeAnnotations())
                     if (t.getLocationInfo().isSameLocationInfo(newLoc))
                         l.add(t);
                 res[i] = buildAnnotatedType(arguments[i],
-                                            newLoc,
-                                            l.toArray(new TypeAnnotation[0]),
-                                            getTypeAnnotations(),
-                                            getDecl());
+                        newLoc,
+                        l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
+                        getTypeAnnotations(),
+                        getDecl());
             }
             return res;
         }
 
+        @Override
+        public AnnotatedType getAnnotatedOwnerType() {
+            Type owner = getParameterizedType().getOwnerType();
+            if (owner == null)
+                return null;
+            LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
+            TypeAnnotation[]all = getTypeAnnotations();
+            List<TypeAnnotation> l = new ArrayList<>(all.length);
+
+            for (TypeAnnotation t : all)
+                if (t.getLocationInfo().isSameLocationInfo(outerLoc))
+                    l.add(t);
+
+            return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
+        }
+
         private ParameterizedType getParameterizedType() {
             return (ParameterizedType)getType();
         }
@@ -279,11 +331,11 @@
         public AnnotatedType[] getAnnotatedUpperBounds() {
             if (!hasUpperBounds()) {
                 return new AnnotatedType[] { buildAnnotatedType(Object.class,
-                                                                LocationInfo.BASE_LOCATION,
-                                                                new TypeAnnotation[0],
-                                                                new TypeAnnotation[0],
-                                                                null)
-                                           };
+                        LocationInfo.BASE_LOCATION,
+                        EMPTY_TYPE_ANNOTATION_ARRAY,
+                        EMPTY_TYPE_ANNOTATION_ARRAY,
+                        null)
+                };
             }
             return getAnnotatedBounds(getWildcardType().getUpperBounds());
         }
@@ -295,21 +347,26 @@
             return getAnnotatedBounds(getWildcardType().getLowerBounds());
         }
 
+        @Overri