--- a/jdk/make/CompileDemos.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/CompileDemos.gmk Thu Dec 17 20:27:37 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/jdk/make/launcher/Launcher-java.base.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/launcher/Launcher-java.base.gmk Thu Dec 17 20:27:37 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/jdk/make/launcher/Launcher-jdk.pack200.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Thu Dec 17 20:27:37 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/jdk/make/launcher/LauncherCommon.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/launcher/LauncherCommon.gmk Thu Dec 17 20:27:37 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/jdk/make/lib/Awt2dLibraries.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/lib/Awt2dLibraries.gmk Thu Dec 17 20:27:37 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/jdk/make/lib/Lib-java.instrument.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/lib/Lib-java.instrument.gmk Thu Dec 17 20:27:37 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/jdk/make/lib/LibCommon.gmk Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/lib/LibCommon.gmk Thu Dec 17 20:27:37 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/jdk/make/mapfiles/libzip/mapfile-vers Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/mapfiles/libzip/mapfile-vers Thu Dec 17 20:27:37 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/jdk/make/mapfiles/libzip/reorder-sparc Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/mapfiles/libzip/reorder-sparc Thu Dec 17 20:27:37 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/jdk/make/mapfiles/libzip/reorder-sparcv9 Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/mapfiles/libzip/reorder-sparcv9 Thu Dec 17 20:27:37 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/jdk/make/mapfiles/libzip/reorder-x86 Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/make/mapfiles/libzip/reorder-x86 Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/io/CharArrayReader.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/io/CharArrayReader.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/io/PushbackReader.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/io/PushbackReader.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/io/StringReader.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/io/StringReader.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/StackWalker.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/security/cert/X509CertSelector.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/cert/X509CertSelector.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/time/Duration.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/AbstractMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/AbstractMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/EnumMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/EnumMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/HashMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/HashMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/IdentityHashMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/IdentityHashMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/Map.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Map.java Thu Dec 17 20:27:37 2015 -0800
@@ -1670,9 +1670,9 @@
*/
@SafeVarargs
@SuppressWarnings("varargs")
- static <K, V> Map<K, V> ofEntries(Entry<K, V>... entries) {
+ static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
Map<K, V> map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null
- for (Entry<K, V> e : entries) {
+ for (Entry<? extends K, ? extends V> e : entries) {
// next line throws NPE if e is null
map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue()));
}
--- a/jdk/src/java.base/share/classes/java/util/TreeMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/TreeMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/WeakHashMap.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/WeakHashMap.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Thu Dec 17 20:27:37 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;
+
+ 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)
+
+ // 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 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
+ }
- // 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);
+ /*
+ * 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<>();
- 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);
+ // 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);
+ }
- private static native String getZipMessage(long jzfile);
+ /*
+ * 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/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,5 +29,6 @@
public interface JavaUtilZipFileAccess {
public boolean startsWithLocHeader(ZipFile zip);
+ public String[] getMetaInfEntryNames(ZipFile zip);
}
--- a/jdk/src/java.base/share/classes/sun/misc/BASE64Decoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/BASE64Encoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/CharacterDecoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/CharacterEncoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/HexDumpEncoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/ProxyGenerator.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/Queue.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/Request.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/RequestProcessor.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/UCDecoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/UCEncoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/UUDecoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/UUEncoder.java Wed Jul 05 21:08:30 2017 +0200
+++ /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/jdk/src/java.base/share/classes/sun/misc/VM.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/misc/VM.java Thu Dec 17 20:27:37 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/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Thu Dec 17 20:27:37 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());
}
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ return null;
+ }
+
private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
AnnotatedType[] res = new AnnotatedType[bounds.length];
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
- LocationInfo newLoc = getLocation().pushWildcard();
int initialCapacity = getTypeAnnotations().length;
for (int i = 0; i < res.length; i++) {
+ LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
for (TypeAnnotation t : getTypeAnnotations())
if (t.getLocationInfo().isSameLocationInfo(newLoc))
l.add(t);
res[i] = buildAnnotatedType(bounds[i],
- newLoc,
- l.toArray(new TypeAnnotation[0]),
- getTypeAnnotations(),
- getDecl());
+ newLoc,
+ l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
+ getTypeAnnotations(),
+ getDecl());
}
return res;
}
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java Thu Dec 17 20:27:37 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -187,13 +187,28 @@
return new LocationInfo(newDepth, res);
}
+ /** Pop a series of locations matching {@code tag}. Stop poping as soon as a non-matching tag is found. */
+ public LocationInfo popAllLocations(byte tag) {
+ LocationInfo l = this;
+ int newDepth = l.depth;
+ while(newDepth > 0 && l.locations[newDepth - 1].tag == tag) {
+ newDepth--;
+ }
+ if (newDepth != l.depth) {
+ Location[] res = new Location[newDepth];
+ System.arraycopy(this.locations, 0, res, 0, newDepth);
+ return new LocationInfo(newDepth, res);
+ } else
+ return l;
+ }
+
public TypeAnnotation[] filter(TypeAnnotation[] ta) {
ArrayList<TypeAnnotation> l = new ArrayList<>(ta.length);
for (TypeAnnotation t : ta) {
if (isSameLocationInfo(t.getLocationInfo()))
l.add(t);
}
- return l.toArray(new TypeAnnotation[0]);
+ return l.toArray(AnnotatedTypeFactory.EMPTY_TYPE_ANNOTATION_ARRAY);
}
boolean isSameLocationInfo(LocationInfo other) {
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Thu Dec 17 20:27:37 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -32,7 +32,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import jdk.internal.misc.SharedSecrets;
@@ -67,9 +66,8 @@
Type type,
TypeAnnotationTarget filter) {
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
- cp,
- decl,
- container);
+ cp, decl, container);
+
List<TypeAnnotation> l = new ArrayList<>(tas.length);
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
@@ -78,10 +76,10 @@
}
TypeAnnotation[] typeAnnotations = l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
return AnnotatedTypeFactory.buildAnnotatedType(type,
- LocationInfo.BASE_LOCATION,
- typeAnnotations,
- typeAnnotations,
- decl);
+ AnnotatedTypeFactory.nestingForType(type, LocationInfo.BASE_LOCATION),
+ typeAnnotations,
+ typeAnnotations,
+ decl);
}
/**
@@ -110,9 +108,8 @@
ArrayList[] l = new ArrayList[size]; // array of ArrayList<TypeAnnotation>
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
- cp,
- decl,
- container);
+ cp, decl, container);
+
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
if (ti.getTarget() == filter) {
@@ -136,10 +133,10 @@
typeAnnotations = EMPTY_TYPE_ANNOTATION_ARRAY;
}
result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i],
- LocationInfo.BASE_LOCATION,
- typeAnnotations,
- typeAnnotations,
- decl);
+ AnnotatedTypeFactory.nestingForType(types[i], LocationInfo.BASE_LOCATION),
+ typeAnnotations,
+ typeAnnotations,
+ decl);
}
return result;
@@ -278,7 +275,7 @@
}
}
res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i],
- loc,
+ AnnotatedTypeFactory.nestingForType(bounds[i], loc),
l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
candidates.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
(AnnotatedElement)decl);
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Thu Dec 17 20:27:37 2015 -0800
@@ -39,7 +39,7 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java Thu Dec 17 20:27:37 2015 -0800
@@ -38,7 +38,7 @@
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.util.ObjectIdentifier;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* Class supporting any PKCS9 attributes.
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Thu Dec 17 20:27:37 2015 -0800
@@ -41,7 +41,7 @@
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import sun.security.x509.KeyUsageExtension;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* A SignerInfo, as defined in PKCS#7's signedData type.
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java Thu Dec 17 20:27:37 2015 -0800
@@ -28,7 +28,7 @@
import java.io.IOException;
import java.util.ArrayList;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import sun.security.x509.GeneralNames;
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/CertId.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/CertId.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import java.security.cert.X509Certificate;
import java.util.Arrays;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPRequest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPRequest.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,7 +30,7 @@
import java.util.Collections;
import java.util.List;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
import sun.security.x509.PKIXExtensions;
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java Thu Dec 17 20:27:37 2015 -0800
@@ -44,7 +44,7 @@
import java.util.Set;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.action.GetIntegerAction;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Thu Dec 17 20:27:37 2015 -0800
@@ -42,7 +42,7 @@
import static sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.CipherType.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.HandshakeMessage.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.Ciphertext.RecordType;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,7 +29,7 @@
import java.security.AccessController;
import java.util.Locale;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import java.nio.ByteBuffer;
import sun.security.action.GetPropertyAction;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Thu Dec 17 20:27:37 2015 -0800
@@ -41,7 +41,7 @@
import javax.crypto.spec.*;
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.internal.spec.*;
import sun.security.internal.interfaces.TlsMasterSecret;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/InputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/InputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,7 +30,7 @@
import java.util.Arrays;
import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -31,7 +31,7 @@
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.Ciphertext.RecordType;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Thu Dec 17 20:27:37 2015 -0800
@@ -31,7 +31,7 @@
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Thu Dec 17 20:27:37 2015 -0800
@@ -2956,7 +2956,7 @@
if (v.length == 0) {
out.println(rb.getString(".Empty.value."));
} else {
- new sun.misc.HexDumpEncoder().encodeBuffer(ext.getExtensionValue(), out);
+ new sun.security.util.HexDumpEncoder().encodeBuffer(ext.getExtensionValue(), out);
out.println();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/HexDumpEncoder.java Thu Dec 17 20:27:37 2015 -0800
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1995, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.security.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * 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 {
+
+ 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;
+ pStream = new PrintStream(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;
+ }
+
+ /** Stream that understands "printing" */
+ protected PrintStream pStream;
+
+ /**
+ * 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);
+ }
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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;
+ }
+ }
+ }
+
+ /**
+ * 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/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Thu Dec 17 20:27:37 2015 -0800
@@ -443,7 +443,7 @@
if (sfAttr != null) {
- //sun.misc.HexDumpEncoder hex = new sun.misc.HexDumpEncoder();
+ //sun.security.util.HexDumpEncoder hex = new sun.security.util.HexDumpEncoder();
//hex.encodeBuffer(data, System.out);
// go through all the attributes and process *-Digest entries
--- a/jdk/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import java.security.cert.CertificateException;
import java.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
@@ -376,6 +376,6 @@
@Override public String toString() {
return super.toString() +
"Unparseable " + name + "extension due to\n" + why + "\n\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(getExtensionValue());
+ new HexDumpEncoder().encodeBuffer(getExtensionValue());
}
}
--- a/jdk/src/java.base/share/classes/sun/security/x509/IPAddressName.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/IPAddressName.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,7 +29,7 @@
import java.lang.Integer;
import java.net.InetAddress;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.BitArray;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
--- a/jdk/src/java.base/share/classes/sun/security/x509/KeyIdentifier.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/KeyIdentifier.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,7 +30,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/UniqueIdentity.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/UniqueIdentity.java Thu Dec 17 20:27:37 2015 -0800
@@ -27,7 +27,7 @@
import java.io.IOException;
import java.math.BigInteger;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -35,7 +35,7 @@
import javax.security.auth.x500.X500Principal;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* <p>Abstract class for a revoked certificate in a CRL.
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -49,7 +49,7 @@
import sun.security.provider.X509Factory;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* <p>
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -41,7 +41,7 @@
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import java.util.Base64;
import sun.security.util.*;
import sun.security.provider.X509Factory;
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertInfo.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertInfo.java Thu Dec 17 20:27:37 2015 -0800
@@ -32,7 +32,7 @@
import java.util.*;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Thu Dec 17 20:27:37 2015 -0800
@@ -38,7 +38,7 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/native/libzip/ZipFile.c Wed Jul 05 21:08:30 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * Copyright (c) 1998, 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
- * 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.
- */
-
-/*
- * Native method support for java.util.zip.ZipFile
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include "jlong.h"
-#include "jvm.h"
-#include "jni.h"
-#include "jni_util.h"
-#include "zip_util.h"
-#ifdef WIN32
-#include "io_util_md.h"
-#else
-#include "io_util.h"
-#endif
-
-#include "java_util_zip_ZipFile.h"
-#include "java_util_jar_JarFile.h"
-
-#define DEFLATED 8
-#define STORED 0
-
-static jfieldID jzfileID;
-
-static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ;
-static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE;
-
-
-/*
- * Declare library specific JNI_Onload entry if static build
- */
-DEF_STATIC_JNI_OnLoad
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls)
-{
- jzfileID = (*env)->GetFieldID(env, cls, "jzfile", "J");
- assert(jzfileID != 0);
-}
-
-static void
-ThrowZipException(JNIEnv *env, const char *msg)
-{
- jstring s = NULL;
- jobject x;
-
- if (msg != NULL) {
- s = JNU_NewStringPlatform(env, msg);
- }
- if (s != NULL) {
- x = JNU_NewObjectByName(env,
- "java/util/zip/ZipException",
- "(Ljava/lang/String;)V", s);
- if (x != NULL) {
- (*env)->Throw(env, x);
- }
- }
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name,
- jint mode, jlong lastModified,
- jboolean usemmap)
-{
- const char *path = JNU_GetStringPlatformChars(env, name, 0);
- char *msg = 0;
- jlong result = 0;
- int flag = 0;
- jzfile *zip = 0;
-
- if (mode & OPEN_READ) flag |= O_RDONLY;
-
- if (path != 0) {
- zip = ZIP_Get_From_Cache(path, &msg, lastModified);
- if (zip == 0 && msg == 0) {
- ZFILE zfd = 0;
-#ifdef WIN32
- if (mode & OPEN_DELETE) flag |= O_TEMPORARY;
- zfd = winFileHandleOpen(env, name, flag);
- if (zfd == -1) {
- /* Exception already pending. */
- goto finally;
- }
-#else
- zfd = open(path, flag, 0);
- if (zfd < 0) {
- throwFileNotFoundException(env, name);
- goto finally;
- }
- if (mode & OPEN_DELETE) {
- unlink(path);
- }
-#endif
- zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap);
- }
-
- if (zip != 0) {
- result = ptr_to_jlong(zip);
- } else if (msg != 0) {
- ThrowZipException(env, msg);
- free(msg);
- } else if (errno == ENOMEM) {
- JNU_ThrowOutOfMemoryError(env, 0);
- } else {
- ThrowZipException(env, "error in opening zip file");
- }
-finally:
- JNU_ReleaseStringPlatformChars(env, name, path);
- }
- return result;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
-
- return zip->total;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
-
- return zip->locsig;
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
-{
- ZIP_Close(jlong_to_ptr(zfile));
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
- jbyteArray name, jboolean addSlash)
-{
-#define MAXNAME 1024
- jzfile *zip = jlong_to_ptr(zfile);
- jsize ulen = (*env)->GetArrayLength(env, name);
- char buf[MAXNAME+2], *path;
- jzentry *ze;
-
- if (ulen > MAXNAME) {
- path = malloc(ulen + 2);
- if (path == 0) {
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- } else {
- path = buf;
- }
- (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
- path[ulen] = '\0';
- ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash);
- if (path != buf) {
- free(path);
- }
- return ptr_to_jlong(ze);
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_freeEntry(JNIEnv *env, jclass cls, jlong zfile,
- jlong zentry)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- jzentry *ze = jlong_to_ptr(zentry);
- ZIP_FreeEntry(zip, ze);
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
- jint n)
-{
- jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
- return ptr_to_jlong(ze);
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->csize != 0 ? DEFLATED : STORED;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->flag;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->csize != 0 ? ze->csize : ze->size;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->size;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return (jlong)ze->time & 0xffffffffUL;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return (jlong)ze->crc & 0xffffffffUL;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_java_util_zip_ZipFile_getCommentBytes(JNIEnv *env,
- jclass cls,
- jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- jbyteArray jba = NULL;
-
- if (zip->comment != NULL) {
- if ((jba = (*env)->NewByteArray(env, zip->clen)) == NULL)
- return NULL;
- (*env)->SetByteArrayRegion(env, jba, 0, zip->clen, (jbyte*)zip->comment);
- }
- return jba;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env,
- jclass cls,
- jlong zentry, jint type)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- int len = 0;
- jbyteArray jba = NULL;
- switch (type) {
- case java_util_zip_ZipFile_JZENTRY_NAME:
- if (ze->name != 0) {
- len = (int)ze->nlen;
- // Unlike for extra and comment, we never return null for
- // an (extremely rarely seen) empty name
- if ((jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
- }
- break;
- case java_util_zip_ZipFile_JZENTRY_EXTRA:
- if (ze->extra != 0) {
- unsigned char *bp = (unsigned char *)&ze->extra[0];
- len = (bp[0] | (bp[1] << 8));
- if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
- }
- break;
- case java_util_zip_ZipFile_JZENTRY_COMMENT:
- if (ze->comment != 0) {
- len = (int)strlen(ze->comment);
- if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
- }
- break;
- }
- return jba;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
- jlong zentry, jlong pos, jbyteArray bytes,
- jint off, jint len)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- char *msg;
-
-#define BUFSIZE 8192
- /* copy via tmp stack buffer: */
- jbyte buf[BUFSIZE];
-
- if (len > BUFSIZE) {
- len = BUFSIZE;
- }
-
- ZIP_Lock(zip);
- len = ZIP_Read(zip, jlong_to_ptr(zentry), pos, buf, len);
- msg = zip->msg;
- ZIP_Unlock(zip);
- if (len != -1) {
- (*env)->SetByteArrayRegion(env, bytes, off, len, buf);
- }
-
- if (len == -1) {
- if (msg != 0) {
- ThrowZipException(env, msg);
- } else {
- char errmsg[128];
- sprintf(errmsg, "errno: %d, error: %s\n",
- errno, "Error reading ZIP file");
- JNU_ThrowIOExceptionWithLastError(env, errmsg);
- }
- }
-
- return len;
-}
-
-/*
- * Returns an array of strings representing the names of all entries
- * that begin with "META-INF/" (case ignored). This native method is
- * used in JarFile as an optimization when looking up manifest and
- * signature file entries. Returns null if no entries were found.
- */
-JNIEXPORT jobjectArray JNICALL
-Java_java_util_jar_JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj)
-{
- jlong zfile = (*env)->GetLongField(env, obj, jzfileID);
- jzfile *zip;
- int i, count;
- jobjectArray result = 0;
-
- if (zfile == 0) {
- JNU_ThrowByName(env,
- "java/lang/IllegalStateException", "zip file closed");
- return NULL;
- }
- zip = jlong_to_ptr(zfile);
-
- /* count the number of valid ZIP metanames */
- count = 0;
- if (zip->metanames != 0) {
- for (i = 0; i < zip->metacount; i++) {
- if (zip->metanames[i] != 0) {
- count++;
- }
- }
- }
-
- /* If some names were found then build array of java strings */
- if (count > 0) {
- jclass cls = JNU_ClassString(env);
- CHECK_NULL_RETURN(cls, NULL);
- result = (*env)->NewObjectArray(env, count, cls, 0);
- CHECK_NULL_RETURN(result, NULL);
- if (result != 0) {
- for (i = 0; i < count; i++) {
- jstring str = (*env)->NewStringUTF(env, zip->metanames[i]);
- if (str == 0) {
- break;
- }
- (*env)->SetObjectArrayElement(env, result, i, str);
- (*env)->DeleteLocalRef(env, str);
- }
- }
- }
- return result;
-}
-
-JNIEXPORT jstring JNICALL
-Java_java_util_zip_ZipFile_getZipMessage(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- char *msg = zip->msg;
- if (msg == NULL) {
- return NULL;
- }
- return JNU_NewStringPlatform(env, msg);
-}
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Thu Dec 17 20:27:37 2015 -0800
@@ -38,6 +38,7 @@
import java.security.*;
import java.util.*;
import java.util.Locale;
+import java.util.concurrent.LinkedBlockingQueue;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.EmbeddedFrame;
@@ -45,7 +46,6 @@
import sun.misc.ManagedLocalsThread;
import sun.misc.MessageUtils;
import sun.misc.PerformanceLogger;
-import sun.misc.Queue;
import sun.security.util.SecurityConstants;
/**
@@ -247,8 +247,7 @@
/**
* AppletEvent Queue
*/
- private Queue<Integer> queue = null;
-
+ private LinkedBlockingQueue<Integer> queue = null;
public synchronized void addAppletListener(AppletListener l) {
listeners = AppletEventMulticaster.add(listeners, l);
@@ -276,10 +275,9 @@
synchronized(this) {
if (queue == null) {
//System.out.println("SEND0= " + id);
- queue = new Queue<>();
+ queue = new LinkedBlockingQueue<>();
}
- Integer eventId = Integer.valueOf(id);
- queue.enqueue(eventId);
+ boolean inserted = queue.add(id);
notifyAll();
}
if (id == APPLET_QUIT) {
@@ -303,8 +301,8 @@
while (queue == null || queue.isEmpty()) {
wait();
}
- Integer eventId = queue.dequeue();
- return new AppletEvent(this, eventId.intValue(), null);
+ int eventId = queue.take();
+ return new AppletEvent(this, eventId, null);
}
boolean emptyEventQueue() {
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Thu Dec 17 20:27:37 2015 -0800
@@ -156,8 +156,6 @@
// rewritten to avoid division:
|| (width * heightSubPixel) >
((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
-// ((edgeSumDeltaY - heightSubPixel) * RLE_THRESHOLD);
-// ((edgeSumDeltaY - heightSubPixel) << BLOCK_TH_LG);
if (doTrace && !useRLE) {
final float meanCrossings
@@ -293,8 +291,10 @@
// update row index to current position:
rowAAChunkIndex[row] = pos;
- // determine need array size (may overflow):
- final long needSize = pos + (px_bbox1 - px0);
+ // determine need array size:
+ // for RLE encoding, position must be aligned to 4 bytes (int):
+ // align - 1 = 3 so add +3 and round-off by mask ~3 = -4
+ final long needSize = pos + ((px_bbox1 - px0 + 3) & -4);
// update next position (bytes):
rowAAChunkPos = needSize;
@@ -401,8 +401,7 @@
// determine need array size:
// pessimistic: max needed size = deltaX x 4 (1 int)
- final int maxLen = (to - from);
- final long needSize = initialPos + (maxLen << 2);
+ final long needSize = initialPos + ((to - from) << 2);
// update row data:
OffHeapArray _rowAAChunk = rowAAChunk;
@@ -465,6 +464,13 @@
// note: last pixel exclusive (>= 0)
// note: it should check X is smaller than 23bits (overflow)!
+ // check address alignment to 4 bytes:
+ if (doCheckUnsafe) {
+ if ((addr_off & 3) != 0) {
+ MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
+ }
+ }
+
// special case to encode entries into a single int:
if (val == 0) {
_unsafe.putInt(addr_off,
@@ -521,6 +527,13 @@
// note: last pixel exclusive (>= 0)
// note: it should check X is smaller than 23bits (overflow)!
+ // check address alignment to 4 bytes:
+ if (doCheckUnsafe) {
+ if ((addr_off & 3) != 0) {
+ MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
+ }
+ }
+
// special case to encode entries into a single int:
if (val == 0) {
_unsafe.putInt(addr_off,
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinConst.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinConst.java Thu Dec 17 20:27:37 2015 -0800
@@ -40,6 +40,8 @@
// log misc.Unsafe alloc/realloc/free
static final boolean logUnsafeMalloc = enableLogs
&& MarlinProperties.isLogUnsafeMalloc();
+ // do check unsafe alignment:
+ static final boolean doCheckUnsafe = false;
// do statistics
static final boolean doStats = enableLogs && MarlinProperties.isDoStats();
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,7 +29,7 @@
import java.io.IOException;
import java.io.ByteArrayInputStream;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* Base class that defines common fields, constants, and debug method.
--- a/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -44,7 +44,7 @@
import javax.naming.ldap.LdapContext;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.provider.certpath.X509CertificatePair;
import sun.security.util.Cache;
import sun.security.util.Debug;
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java Thu Dec 17 20:27:37 2015 -0800
@@ -34,7 +34,7 @@
import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* This class encapsulates a Kerberos ticket and associated
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,7 +30,7 @@
import javax.crypto.SecretKey;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.EncryptionKey;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Thu Dec 17 20:27:37 2015 -0800
@@ -26,7 +26,7 @@
package sun.security.jgss.krb5;
import org.ietf.jgss.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.GSSCaller;
import sun.security.jgss.spi.*;
@@ -1415,7 +1415,7 @@
@Override
public String toString() {
return "Kerberos session key: etype: " + key.getEType() + "\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(key.getBytes());
+ new HexDumpEncoder().encodeBuffer(key.getBytes());
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Thu Dec 17 20:27:37 2015 -0800
@@ -227,7 +227,7 @@
} catch (Exception e) {
if (DEBUG) {
System.out.println("Unable to parse eData field of KRB-ERROR:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data));
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data));
}
IOException ioe = new IOException(
"Unable to parse eData field of KRB-ERROR");
@@ -237,7 +237,7 @@
} else {
if (DEBUG) {
System.out.println("Unknown eData field of KRB-ERROR:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data));
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data));
}
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Thu Dec 17 20:27:37 2015 -0800
@@ -306,8 +306,8 @@
public static final boolean DEBUG =
java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
- public static final sun.misc.HexDumpEncoder hexDumper =
- new sun.misc.HexDumpEncoder();
+ public static final sun.security.util.HexDumpEncoder hexDumper =
+ new sun.security.util.HexDumpEncoder();
static {
errMsgList = new Hashtable<Integer,String> ();
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java Thu Dec 17 20:27:37 2015 -0800
@@ -306,7 +306,7 @@
} else if (s2kparams.length == 0) {
sb.append("empty\n");
} else {
- sb.append(new sun.misc.HexDumpEncoder()
+ sb.append(new sun.security.util.HexDumpEncoder()
.encodeBuffer(s2kparams));
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java Thu Dec 17 20:27:37 2015 -0800
@@ -40,7 +40,7 @@
import java.nio.charset.Charset;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.krb5.Confounder;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.krb5.KrbCryptoException;
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import java.util.logging.Logger;
import java.util.logging.Level;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* The base class used by client and server implementations of SASL
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Thu Dec 17 20:27:37 2015 -0800
@@ -44,7 +44,7 @@
import sun.security.krb5.*;
import sun.security.jgss.krb5.Krb5Util;
import sun.security.krb5.Credentials;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* This {@code LoginModule} authenticates users using
--- a/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Thu Dec 17 20:27:37 2015 -0800
@@ -64,6 +64,6 @@
public String toString() {
return "AuthorizationDataEntry: type="+type+", data=" +
data.length + " bytes:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data);
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data);
}
}
--- a/jdk/test/ProblemList.txt Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/ProblemList.txt Thu Dec 17 20:27:37 2015 -0800
@@ -126,6 +126,9 @@
java/beans/Introspector/8132566/OverridePropertyInfoTest.java generic-all
java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java generic-all
+# 8145589
+java/beans/Introspector/Test6277246.java generic-all
+
############################################################################
# jdk_lang
--- a/jdk/test/TEST.groups Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/TEST.groups Thu Dec 17 20:27:37 2015 -0800
@@ -95,16 +95,19 @@
-:jdk_concurrent \
-:jdk_stream
-# java.util.concurrent (JSR-166)
+# All collections, core and concurrent
+jdk_collections = \
+ :jdk_collections_core \
+ :jdk_concurrent
+
+# java.util.concurrent
+# Includes concurrent collections plus other stuff
# Maintained by JSR-166 EG (Doug Lea et al)
-# Deque and PriorityQueue are also generally maintained by JSR-166
jdk_concurrent = \
- java/util/concurrent \
- java/util/Deque \
- java/util/PriorityQueue
+ java/util/concurrent
-# Java Collections Framework
-jdk_collections = \
+# Java Collections Framework core classes
+jdk_collections_core = \
java/util/AbstractCollection \
java/util/AbstractList \
java/util/AbstractMap \
@@ -114,19 +117,22 @@
java/util/BitSet \
java/util/Collection \
java/util/Collections \
+ java/util/Comparator \
+ java/util/Deque \
java/util/EnumMap \
java/util/EnumSet \
- java/util/Comparator \
- java/util/Iterator \
java/util/HashMap \
+ java/util/HashSet \
java/util/Hashtable \
java/util/IdentityHashMap \
- java/util/List \
+ java/util/Iterator \
java/util/LinkedHashMap \
java/util/LinkedHashSet \
java/util/LinkedList \
+ java/util/List \
java/util/Map \
java/util/NavigableMap \
+ java/util/PriorityQueue \
java/util/TimSort \
java/util/TreeMap \
java/util/Vector \
--- a/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java Thu Dec 17 20:27:37 2015 -0800
@@ -65,7 +65,10 @@
byte[] aad2 = aad.clone();
aad2[50]++;
- GCMParameterSpec spec = new GCMParameterSpec(128, new byte[16]);
+ byte[] iv = new byte[16];
+ rdm.nextBytes(iv);
+
+ GCMParameterSpec spec = new GCMParameterSpec(128, iv);
Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
encCipher.init(Cipher.ENCRYPT_MODE, key, spec);
encCipher.updateAAD(aad);
--- a/jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java Thu Dec 17 20:27:37 2015 -0800
@@ -126,7 +126,11 @@
}
// Now try to encrypt again using a different parameter; should work
- c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, new byte[30]));
+ byte[] rdm_iv = new byte[30];
+ Random rdm = new Random();
+ rdm.nextBytes(rdm_iv);
+
+ c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, rdm_iv));
c.updateAAD(AAD);
c.doFinal(PT);
// subsequent encryption should fail unless re-init w/ different key+iv
--- a/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Thu Dec 17 20:27:37 2015 -0800
@@ -25,7 +25,6 @@
* @test
* @bug 7146728
* @summary DHKeyAgreement2
- * @modules java.base/sun.misc
* @author Jan Luehe
*/
@@ -38,8 +37,6 @@
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
-import sun.misc.HexDumpEncoder;
-
/**
* This test utility executes the Diffie-Hellman key agreement protocol
* between 2 parties: Alice and Bob.
--- a/jdk/test/com/sun/jdi/SuspendThreadTest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/sun/jdi/SuspendThreadTest.java Thu Dec 17 20:27:37 2015 -0800
@@ -42,6 +42,7 @@
class SuspendThreadTarg {
public static long count;
+ public static boolean active = true;
public static void bkpt() {
count++;
@@ -53,7 +54,7 @@
// We need this to be running so the bkpt
// can be hit immediately when it is enabled
// in the back-end.
- while(count >= 0) {
+ while(active) {
bkpt();
}
System.out.println("Goodbye from SuspendThreadTarg, count = " + count);
@@ -82,9 +83,9 @@
// to guard against spurious wakeups from bkptSignal.wait()
boolean signalSent;
// signal that a breakpoint has happened
- Object bkptSignal = new Object() {};
+ final private Object bkptSignal = new Object() {};
BreakpointRequest bkptRequest;
- Field debuggeeCountField;
+ Field debuggeeCountField, debuggeeActiveField;
// When we get a bkpt we want to disable the request,
// resume the debuggee, and then re-enable the request
@@ -119,65 +120,71 @@
/********** test core **********/
protected void runTests() throws Exception {
- /*
- * Get to the top of main()
- * to determine targetClass and mainThread
- */
- BreakpointEvent bpe = startToMain("SuspendThreadTarg");
- targetClass = (ClassType)bpe.location().declaringType();
- mainThread = bpe.thread();
- EventRequestManager erm = vm().eventRequestManager();
+ try {
+ /*
+ * Get to the top of main()
+ * to determine targetClass and mainThread
+ */
+ BreakpointEvent bpe = startToMain("SuspendThreadTarg");
+ targetClass = (ClassType)bpe.location().declaringType();
+ mainThread = bpe.thread();
+ EventRequestManager erm = vm().eventRequestManager();
- Location loc1 = findMethod(targetClass, "bkpt", "()V").location();
+ Location loc1 = findMethod(targetClass, "bkpt", "()V").location();
- bkptRequest = erm.createBreakpointRequest(loc1);
+ bkptRequest = erm.createBreakpointRequest(loc1);
- // Without this, it is a SUSPEND_ALL bkpt and the test will pass
- bkptRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
- bkptRequest.enable();
+ // Without this, it is a SUSPEND_ALL bkpt and the test will pass
+ bkptRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+ bkptRequest.enable();
- debuggeeCountField = targetClass.fieldByName("count");
- try {
- addListener (this);
- } catch (Exception ex){
- ex.printStackTrace();
- failure("failure: Could not add listener");
- throw new Exception("SuspendThreadTest: failed", ex);
- }
+ debuggeeCountField = targetClass.fieldByName("count");
+ debuggeeActiveField = targetClass.fieldByName("active");
+ try {
+ addListener (this);
+ } catch (Exception ex){
+ ex.printStackTrace();
+ failure("failure: Could not add listener");
+ throw new Exception("SuspendThreadTest: failed", ex);
+ }
- int prevBkptCount;
- vm().resume();
- synchronized (bkptSignal) {
- while (bkptCount < maxBkpts) {
- prevBkptCount = bkptCount;
- // If we don't get a bkpt within 5 secs,
- // the test fails
- signalSent = false;
- do {
- try {
- bkptSignal.wait(5000);
- } catch (InterruptedException ee) {
+ int prevBkptCount;
+ vm().resume();
+ synchronized (bkptSignal) {
+ while (bkptCount < maxBkpts) {
+ prevBkptCount = bkptCount;
+ // If we don't get a bkpt within 5 secs,
+ // the test fails
+ signalSent = false;
+ do {
+ try {
+ bkptSignal.wait(5000);
+ } catch (InterruptedException ee) {
+ }
+ } while (signalSent == false);
+ if (prevBkptCount == bkptCount) {
+ failure("failure: test hung");
+ break;
}
- } while (signalSent == false);
- if (prevBkptCount == bkptCount) {
- failure("failure: test hung");
- break;
}
}
- }
- println("done with loop");
- bkptRequest.disable();
- removeListener(this);
-
+ println("done with loop");
+ bkptRequest.disable();
+ removeListener(this);
- /*
- * deal with results of test
- * if anything has called failure("foo") testFailed will be true
- */
- if (!testFailed) {
- println("SuspendThreadTest: passed");
- } else {
- throw new Exception("SuspendThreadTest: failed");
+ /*
+ * deal with results of test
+ * if anything has called failure("foo") testFailed will be true
+ */
+ if (!testFailed) {
+ println("SuspendThreadTest: passed");
+ } else {
+ throw new Exception("SuspendThreadTest: failed");
+ }
+ } finally {
+ if (targetClass != null && debuggeeActiveField != null) {
+ targetClass.setValue(debuggeeActiveField, vm().mirrorOf(false));
+ }
}
}
}
--- a/jdk/test/com/sun/jndi/ldap/Base64Test.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/sun/jndi/ldap/Base64Test.java Thu Dec 17 20:27:37 2015 -0800
@@ -164,7 +164,7 @@
private static void deserialize(byte[] bytes) throws Exception {
//System.out.println("\nSerialized RefAddr object: ");
- //System.out.println(new sun.misc.HexDumpEncoder().encode(bytes));
+ //System.out.println(new sun.security.util.HexDumpEncoder().encode(bytes));
ObjectInputStream objectStream =
new ObjectInputStream(new ByteArrayInputStream(bytes));
--- a/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Thu Dec 17 20:27:37 2015 -0800
@@ -25,13 +25,14 @@
* @test
* @bug 6911951 7150092
* @summary NTLM should be a supported Java SASL mechanism
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.util
* java.security.sasl
*/
import java.io.IOException;
import javax.security.sasl.*;
import javax.security.auth.callback.*;
import java.util.*;
+import sun.security.util.HexDumpEncoder;
public class NTLMTest {
@@ -311,7 +312,7 @@
byte[] response = (clnt.hasInitialResponse()
? clnt.evaluateChallenge(EMPTY) : EMPTY);
System.out.println("Initial:");
- new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
+ new HexDumpEncoder().encodeBuffer(response, System.out);
byte[] challenge;
while (!clnt.isComplete() || !srv.isComplete()) {
@@ -319,12 +320,12 @@
response = null;
if (challenge != null) {
System.out.println("Challenge:");
- new sun.misc.HexDumpEncoder().encodeBuffer(challenge, System.out);
+ new HexDumpEncoder().encodeBuffer(challenge, System.out);
response = clnt.evaluateChallenge(challenge);
}
if (response != null) {
System.out.println("Response:");
- new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
+ new HexDumpEncoder().encodeBuffer(response, System.out);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/PushbackReader/ReadCloseRaceNPE.java Thu Dec 17 20:27:37 2015 -0800
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8143394
+ * @summary Check for NullPointerException in race between read() and close().
+ */
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+public class ReadCloseRaceNPE {
+
+ private static final int BUF_SIZE = 1000;
+ private static final long TIMEOUT_MS = 3000;
+
+ private static final List<Exception> failures = new ArrayList<>();
+
+ private static void testReader(final Supplier<Reader> readerSupplier)
+ throws InterruptedException {
+ AtomicReference<Reader> readerRef =
+ new AtomicReference<>(readerSupplier.get());
+
+ AtomicBoolean isFinished = new AtomicBoolean();
+
+ Runnable readTask = () -> {
+ long startTime = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startTime < TIMEOUT_MS) {
+ try {
+ readerRef.get().read();
+ } catch (Exception e) {
+ if (!(e instanceof IOException)) {
+ failures.add(e);
+ break;
+ }
+ readerRef.set(readerSupplier.get());
+ }
+ }
+ isFinished.set(true);
+ };
+
+ Runnable closeTask = () -> {
+ while (!isFinished.get()) {
+ try {
+ readerRef.get().close();
+ } catch (Exception e) {
+ if (!(e instanceof IOException)) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+
+ Thread readThread = new Thread(readTask);
+ Thread closeThread = new Thread(closeTask);
+
+ readThread.start();
+ closeThread.start();
+ readThread.join();
+ closeThread.join();
+ }
+
+ public static void main(String[] args) throws Throwable {
+ final String s = "Two riders were approaching.\\n";
+
+ Supplier<Reader> charPushbackReaderSupplier = () -> {
+ char buf[] = new char[s.length()];
+ s.getChars(0, s.length(), buf, 0);
+ CharArrayReader in = new CharArrayReader(buf);
+ return new PushbackReader(in, BUF_SIZE);
+ };
+
+ testReader(charPushbackReaderSupplier);
+
+ Supplier<Reader> stringPushbackReaderSupplier = () -> {
+ StringReader in = new StringReader(s);
+ return new PushbackReader(in, BUF_SIZE);
+ };
+
+ testReader(stringPushbackReaderSupplier);
+
+ if (!failures.isEmpty()) {
+ failures.stream().forEach((x) -> ((Exception) x).printStackTrace());
+ throw new RuntimeException("PushbackReaderNPE failed");
+ }
+ }
+}
--- a/jdk/test/java/lang/StackWalker/MultiThreadStackWalk.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/lang/StackWalker/MultiThreadStackWalk.java Thu Dec 17 20:27:37 2015 -0800
@@ -328,7 +328,7 @@
public void run() {
try {
- Env env = runTest(test, 2000, 10);
+ Env env = runTest(test, 1000, 10);
//waitWalkers(env);
checkTest(env, test);
} catch(Throwable t) {
--- a/jdk/test/java/lang/StackWalker/StackWalkTest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java Thu Dec 17 20:27:37 2015 -0800
@@ -236,6 +236,8 @@
if (didWalk) {
throw new IllegalStateException("StackWalkTest already used");
}
+ // Test may run into StackOverflow when running in -Xcomp mode on deep stack
+ assert stackDepth <= 1000;
assert markAt <= stackDepth : "markAt(" + markAt + ") > stackDepth("
+ stackDepth + ")";
System.out.print("runTest(" + swOptions
@@ -297,15 +299,15 @@
// Long stack, default maxDepth
StackWalkTest swt;
swt = new StackWalkTest();
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
// Long stack, matching maxDepth
swt = new StackWalkTest(2000);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
// Long stack, maximum maxDepth
swt = new StackWalkTest(Integer.MAX_VALUE);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
//
// Single batch
@@ -349,7 +351,7 @@
swt.runTest(StackWalkTest.class, "main", 80, 40);
swt = new StackWalkTest(EnumSet.of(RETAIN_CLASS_REFERENCE), 50);
- swt.runTest(StackWalkTest.class, "main", 2000, 1048);
+ swt.runTest(StackWalkTest.class, "main", 1000, 524);
}
}
}
--- a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Thu Dec 17 20:27:37 2015 -0800
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8004698 8007073 8022343 8054304 8058595
+ * @bug 8004698 8007073 8022343 8054304 8057804 8058595
* @summary Unit test for type annotations
*/
@@ -358,6 +358,31 @@
check(annos.length == 2);
check(((TypeAnno)annos[0]).value().equals("I1"));
check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
+
+ // check type args
+ Field f = TestParameterizedType.class.getDeclaredField("theField");
+ AnnotatedParameterizedType fType = (AnnotatedParameterizedType)f.getAnnotatedType();
+ args = fType.getAnnotatedActualTypeArguments();
+ check(args.length == 1);
+ annos = args[0].getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno2)annos[0]).value().equals("Map Arg"));
+ check(args[0].getAnnotation(TypeAnno2.class).value().equals("Map Arg"));
+
+ // check outer type type args
+ fType = (AnnotatedParameterizedType)fType.getAnnotatedOwnerType();
+ args = fType.getAnnotatedActualTypeArguments();
+ check(args.length == 1);
+ annos = args[0].getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno2)annos[0]).value().equals("String Arg"));
+ check(args[0].getAnnotation(TypeAnno2.class).value().equals("String Arg"));
+
+ // check outer type normal type annotations
+ annos = fType.getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno)annos[0]).value().equals("FieldOuter"));
+ check(fType.getAnnotation(TypeAnno.class).value().equals("FieldOuter"));
}
private static void testWildcardType() throws Exception {
@@ -563,9 +588,12 @@
abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
- @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
+ @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
return null;
}
+
+ public @TypeAnno("FieldOuter") ParameterizedOuter<@TypeAnno2("String Arg") String>.
+ @TypeAnno("FieldInner")ParameterizedInner<@TypeAnno2("Map Arg")Map> theField;
}
class ParameterizedOuter <T> {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedOwnerType.java Thu Dec 17 20:27:37 2015 -0800
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8058595
+ * @summary Test that AnnotatedType.getAnnotatedOwnerType() works as expected
+ *
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Asserts
+ * @run main GetAnnotatedOwnerType
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import jdk.testlibrary.Asserts;
+
+public class GetAnnotatedOwnerType<Dummy> {
+ public @TA("generic") GetAnnotatedOwnerType<String> . @TB("generic") Nested<Integer> genericField;
+ public @TA("raw") GetAnnotatedOwnerType . @TB("raw") Nested rawField;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("non-generic") Inner nonGeneric;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("generic") InnerGeneric<String> innerGeneric;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("raw") InnerGeneric innerRaw;
+ public Object anonymous = new Object() {};
+ public @TA("array") Dummy[] dummy;
+ public @TA("wildcard") GetAnnotatedOwnerType<?> wildcard;
+ public @TA("typevariable") Dummy tv;
+ public @TA("bad") GetAnnotatedOwnerType<@TA("good") GetAnnotatedOwnerType<String> . @TB("tb") Nested<Integer> > typeArgument;
+ public GetAnnotatedOwnerType< GetAnnotatedOwnerType<String> .
+ B .
+ C<Class<?>, ? extends @TA("complicated") Exception> .
+ D<Number> > [] complicated;
+
+ public static void main(String[] args) throws Exception {
+ testGeneric();
+ testRaw();
+ testNonGeneric();
+ testInnerGeneric();
+ testInnerRaw();
+
+ testLocalClass();
+ testAnonymousClass();
+
+ testArray();
+ testWildcard();
+ testTypeParameter();
+
+ testTypeArgument();
+ testComplicated();
+ }
+
+ public static void testGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("genericField");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testRaw() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("rawField");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "raw");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testNonGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("nonGeneric");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "non-generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testInnerGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("innerGeneric");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testInnerRaw() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("innerRaw");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testLocalClass() throws Exception {
+ class ALocalClass {}
+ class OneMore {
+ public @TA("null") ALocalClass c;
+ }
+ testNegative(OneMore.class.getField("c").getAnnotatedType(), "Local class should return null");
+ }
+
+ public static void testAnonymousClass() throws Exception {
+ testNegative(GetAnnotatedOwnerType.class.getField("anonymous").getAnnotatedType(),
+ "Anonymous class should return null");
+ }
+
+ public static void testArray() throws Exception {
+ AnnotatedType t = GetAnnotatedOwnerType.class.getField("dummy").getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedArrayType),
+ "Was expecting an AnnotatedArrayType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testWildcard() throws Exception {
+ AnnotatedType tt = GetAnnotatedOwnerType.class.getField("wildcard").getAnnotatedType();
+ AnnotatedType t = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertTrue((t instanceof AnnotatedWildcardType),
+ "Was expecting an AnnotatedWildcardType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testTypeParameter() throws Exception {
+ AnnotatedType t = GetAnnotatedOwnerType.class.getField("tv").getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedTypeVariable),
+ "Was expecting an AnnotatedTypeVariable " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testTypeArgument() throws Exception {
+ AnnotatedType tt = GetAnnotatedOwnerType.class.getField("typeArgument").getAnnotatedType();
+ Asserts.assertEquals(tt.getAnnotation(TA.class).value(), "bad");
+ Asserts.assertTrue(tt.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + tt.getAnnotations().length);
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "tb");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "good");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testComplicated() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("complicated");
+
+ // Outermost level
+ AnnotatedType t = f.getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedArrayType),
+ "Was expecting an AnnotatedArrayType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // Component type
+ t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // Type arg GetAnnotatedOwnerType<String>...D<Number>
+ t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // C<Class<?>, ? extends ...>
+ t = t.getAnnotatedOwnerType();
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // ? extends
+ t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[1];
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // @TA("complicated") Exception
+ t = ((AnnotatedWildcardType)t).getAnnotatedUpperBounds()[0];
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertEquals(t.getAnnotation(TA.class).value(), "complicated");
+ Asserts.assertTrue(t.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + t.getAnnotations().length);
+ }
+
+ private static void testNegative(AnnotatedType t, String msg) {
+ Asserts.assertNull(t.getAnnotatedOwnerType(), msg);
+ }
+
+ public class Nested<AlsoDummy> {}
+ public class B {
+ public class C<R, S> {
+ public class D<T> {
+ }
+ }
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface TA {
+ String value();
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface TB {
+ String value();
+ }
+}
+
+class GetAnnotatedOwnerTypeAuxilliary {
+ class Inner {}
+
+ class InnerGeneric<Dummy> {}
+}
--- a/jdk/test/java/lang/reflect/Proxy/CharType.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/lang/reflect/Proxy/CharType.java Thu Dec 17 20:27:37 2015 -0800
@@ -24,7 +24,7 @@
/*
* @test
* @bug 4346224
- * @summary Test against a typo in sun.misc.ProxyGenerator:
+ * @summary Test against a typo in ProxyGenerator:
* "java/lang/Character" should be used instead of
* "java/lang/Char".
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug8139572.java Thu Dec 17 20:27:37 2015 -0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8139572
+ * @summary SimpleDateFormat parse month stand-alone format bug
+ * @compile -encoding utf-8 Bug8139572.java
+ * @run main Bug8139572
+ */
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+public class Bug8139572 {
+
+ private static final Locale RUSSIAN = new Locale("ru");
+ private static final Date SEPT12 = new GregorianCalendar(2015, Calendar.SEPTEMBER, 12).getTime();
+
+ private static final String[] PATTERNS = {
+ "L",
+ "dd L",
+ "dd L yy",
+ "dd L yyyy",
+ "LL",
+ "dd LL",
+ "dd LL yy",
+ "dd LL yyyy",
+ "LLL",
+ "dd LLL",
+ "dd LLL yy",
+ "dd LLL yyyy",
+ "LLLL",
+ "dd LLLL",
+ "dd LLLL yy",
+ "dd LLLL yyyy"
+ };
+
+ private static final String[] APPLIED = {
+ "9",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "09",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "сентября",
+ "12 сентября",
+ "12 сентября 15",
+ "12 сентября 2015",
+ "сентября",
+ "12 сентября",
+ "12 сентября 15",
+ "12 сентября 2015"
+ };
+
+ private static final String[] EXPECTED = {
+ "9",
+ "12 9",
+ "12 9 15",
+ "12 9 2015",
+ "09",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "сент.",
+ "12 сент.",
+ "12 сент. 15",
+ "12 сент. 2015",
+ "сентябрь",
+ "12 сентябрь",
+ "12 сентябрь 15",
+ "12 сентябрь 2015"
+ };
+
+ public static void main(String[] args) throws ParseException {
+
+ for (int i = 0; i < PATTERNS.length; i++) {
+ SimpleDateFormat fmt = new SimpleDateFormat(PATTERNS[i], RUSSIAN);
+ Date standAloneDate = fmt.parse(APPLIED[i]);
+ String str = fmt.format(standAloneDate);
+ if (!EXPECTED[i].equals(str)) {
+ throw new RuntimeException("bad result: got '" + str + "', expected '" + EXPECTED[i] + "'");
+ }
+ }
+
+ SimpleDateFormat fmt = new SimpleDateFormat("", RUSSIAN);
+ for (int j = 0; j < PATTERNS.length; j++) {
+ fmt.applyPattern(PATTERNS[j]);
+ String str = fmt.format(SEPT12);
+ if (!EXPECTED[j].equals(str)) {
+ throw new RuntimeException("bad result: got '" + str + "', expected '" + EXPECTED[j] + "'");
+ }
+ }
+ }
+}
--- a/jdk/test/java/time/tck/java/time/TCKDuration.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/time/tck/java/time/TCKDuration.java Thu Dec 17 20:27:37 2015 -0800
@@ -2393,6 +2393,65 @@
}
//-----------------------------------------------------------------------
+ // dividedbyDur()
+ //-----------------------------------------------------------------------
+
+ @DataProvider(name="dividedByDur_provider")
+ Object[][] provider_dividedByDur() {
+ return new Object[][] {
+ {Duration.ofSeconds(0, 0), Duration.ofSeconds(1, 0), 0},
+ {Duration.ofSeconds(1, 0), Duration.ofSeconds(1, 0), 1},
+ {Duration.ofSeconds(6, 0), Duration.ofSeconds(3, 0), 2},
+ {Duration.ofSeconds(3, 0), Duration.ofSeconds(6, 0), 0},
+ {Duration.ofSeconds(7, 0), Duration.ofSeconds(3, 0), 2},
+
+ {Duration.ofSeconds(0, 333_333_333), Duration.ofSeconds(0, 333_333_333), 1},
+ {Duration.ofSeconds(0, 666_666_666), Duration.ofSeconds(0, 333_333_333), 2},
+ {Duration.ofSeconds(0, 333_333_333), Duration.ofSeconds(0, 666_666_666), 0},
+ {Duration.ofSeconds(0, 777_777_777), Duration.ofSeconds(0, 333_333_333), 2},
+
+ {Duration.ofSeconds(-7, 0), Duration.ofSeconds(3, 0), -2},
+ {Duration.ofSeconds(0, 7), Duration.ofSeconds(0, -3), -2},
+ {Duration.ofSeconds(0, -777_777_777), Duration.ofSeconds(0, 333_333_333), -2},
+
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), 29},
+ {Duration.ofSeconds(-432000L, 777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(14400L, -333_333_333L), -30},
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(-14400L, 333_333_333L), -30},
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(-14400L, -333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(-14400L, -333_333_333L), 29},
+
+ {Duration.ofSeconds(Long.MAX_VALUE, 0), Duration.ofSeconds(1, 0), Long.MAX_VALUE},
+ {Duration.ofSeconds(Long.MAX_VALUE, 0), Duration.ofSeconds(Long.MAX_VALUE, 0), 1},
+ };
+ }
+
+ @Test(dataProvider="dividedByDur_provider")
+ public void test_dividedByDur(Duration dividend, Duration divisor, long expected) {
+ assertEquals(dividend.dividedBy(divisor), expected);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void test_dividedByDur_zero() {
+ Duration t = Duration.ofSeconds(1, 0);
+ t.dividedBy(Duration.ZERO);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void test_dividedByDur_null() {
+ Duration t = Duration.ofSeconds(1, 0);
+ t.dividedBy(null);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void test_dividedByDur_overflow() {
+ Duration dur1 = Duration.ofSeconds(Long.MAX_VALUE, 0);
+ Duration dur2 = Duration.ofNanos(1);
+ dur1.dividedBy(dur2);
+ }
+
+ //-----------------------------------------------------------------------
// negated()
//-----------------------------------------------------------------------
@Test
--- a/jdk/test/java/util/Map/MapFactories.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/util/Map/MapFactories.java Thu Dec 17 20:27:37 2015 -0800
@@ -377,4 +377,13 @@
assertEquals(sie.toString(), kvh1.toString());
}
+ // compile-time test of wildcards
+ @Test
+ public void entryWildcardTests() {
+ Map.Entry<Integer,Double> e1 = Map.entry(1, 2.0);
+ Map.Entry<Float,Long> e2 = Map.entry(3.0f, 4L);
+ Map<Number,Number> map = Map.ofEntries(e1, e2);
+ assertEquals(map.size(), 2);
+ }
+
}
--- a/jdk/test/java/util/regex/PatternStreamTest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/util/regex/PatternStreamTest.java Thu Dec 17 20:27:37 2015 -0800
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8016846 8024341 8071479
+ * @bug 8016846 8024341 8071479 8145006
* @summary Unit tests stream and lambda-based methods on Pattern and Matcher
* @library ../stream/bootlib/java.base
* @build java.util.stream.OpTestCase
@@ -42,6 +42,7 @@
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.LambdaTestHelpers;
import java.util.stream.OpTestCase;
import java.util.stream.Stream;
@@ -185,6 +186,20 @@
.exercise();
}
+ @Test
+ public void testLateBinding() {
+ Pattern pattern = Pattern.compile(",");
+
+ StringBuilder sb = new StringBuilder("a,b,c,d,e");
+ Stream<String> stream = pattern.splitAsStream(sb);
+ sb.setLength(3);
+ assertEquals(Arrays.asList("a", "b"), stream.collect(Collectors.toList()));
+
+ stream = pattern.splitAsStream(sb);
+ sb.append(",f,g");
+ assertEquals(Arrays.asList("a", "b", "f", "g"), stream.collect(Collectors.toList()));
+ }
+
public void testFailfastMatchResults() {
Pattern p = Pattern.compile("X");
Matcher m = p.matcher("XX");
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java Thu Dec 17 20:27:37 2015 -0800
@@ -56,6 +56,7 @@
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.flatMapping;
+import static java.util.stream.Collectors.filtering;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.groupingByConcurrent;
import static java.util.stream.Collectors.mapping;
@@ -72,7 +73,7 @@
/*
* @test
- * @bug 8071600
+ * @bug 8071600 8144675
* @summary Test for collectors.
*/
public class CollectorsTest extends OpTestCase {
@@ -118,6 +119,23 @@
}
}
+ static class FilteringAssertion<T, R> extends CollectorAssertion<T, R> {
+ private final Predicate<T> filter;
+ private final CollectorAssertion<T, R> downstream;
+
+ public FilteringAssertion(Predicate<T> filter, CollectorAssertion<T, R> downstream) {
+ this.filter = filter;
+ this.downstream = downstream;
+ }
+
+ @Override
+ void assertValue(R value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+ downstream.assertValue(value,
+ () -> source.get().filter(filter),
+ ordered);
+ }
+ }
+
static class GroupingByAssertion<T, K, V, M extends Map<K, ? extends V>> extends CollectorAssertion<T, M> {
private final Class<? extends Map> clazz;
private final Function<T, K> classifier;
@@ -551,6 +569,36 @@
}
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+ public void testGroupingByWithFiltering(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+ Function<Integer, Integer> classifier = i -> i % 3;
+ Predicate<Integer> filteringByMod2 = i -> i % 2 == 0;
+ Predicate<Integer> filteringByUnder100 = i -> i % 2 < 100;
+ Predicate<Integer> filteringByTrue = i -> true;
+ Predicate<Integer> filteringByFalse = i -> false;
+
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByMod2, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByMod2,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByUnder100, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByUnder100,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByTrue, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByTrue,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByFalse, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByFalse,
+ new ToListAssertion<>())));
+ }
+
+ @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
public void testTwoLevelGroupingBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
Function<Integer, Integer> classifier = i -> i % 6;
Function<Integer, Integer> classifier2 = i -> i % 23;
--- a/jdk/test/java/util/zip/TestZipError.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/util/zip/TestZipError.java Thu Dec 17 20:27:37 2015 -0800
@@ -84,9 +84,10 @@
try {
while (entries.hasMoreElements()) {
ze = entries.nextElement();
+ zf.getInputStream(ze).readAllBytes();
}
fail("Did not get expected exception");
- } catch (ZipError e) {
+ } catch (ZipException e) {
pass();
} catch (InternalError e) {
fail("Caught InternalError instead of expected ZipError");
--- a/jdk/test/java/util/zip/ZipFile/ReadZip.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/java/util/zip/ZipFile/ReadZip.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,6 +30,7 @@
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.zip.*;
@@ -110,6 +111,6 @@
"input"
+ String.valueOf(new java.util.Random().nextInt())
+ ".zip")));
- } catch (FileNotFoundException fnfe) {}
+ } catch (NoSuchFileException nsfe) {}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ZipFile/TestZipFile.java Thu Dec 17 20:27:37 2015 -0800
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8142508
+ * @summary Tests various ZipFile apis
+ * @run main/manual TestZipFile
+ */
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.nio.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.zip.*;
+
+public class TestZipFile {
+
+ private static Random r = new Random();
+ private static int N = 50;
+ private static int NN = 10;
+ private static int ENUM = 10000;
+ private static int ESZ = 10000;
+ private static ExecutorService executor = Executors.newFixedThreadPool(20);
+ private static Set<Path> paths = new HashSet<>();
+
+ static void realMain (String[] args) throws Throwable {
+
+ try {
+ for (int i = 0; i < N; i++) {
+ test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ test(r.nextInt(ENUM), r.nextInt(ESZ), true, true);
+ }
+
+ for (int i = 0; i < NN; i++) {
+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), false, true);
+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), true, true);
+ testCachedDelete();
+ testCachedOverwrite();
+ //test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ }
+
+ test(70000, 1000, false, true); // > 65536 entry number;
+ testDelete(); // OPEN_DELETE
+
+ executor.shutdown();
+ executor.awaitTermination(10, TimeUnit.MINUTES);
+ } finally {
+ for (Path path : paths) {
+ Files.deleteIfExists(path);
+ }
+ }
+ }
+
+ static void test(int numEntry, int szMax, boolean addPrefix, boolean cleanOld) {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip = new Zip(name, numEntry, szMax, addPrefix, cleanOld);
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip));
+ }
+ }
+
+ // test scenario:
+ // (1) open the ZipFile(zip) with OPEN_READ | OPEN_DELETE
+ // (2) test the ZipFile works correctly
+ // (3) check the zip is deleted after ZipFile gets closed
+ static void testDelete() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ try (ZipFile zf = new ZipFile(new File(zip.name),
+ ZipFile.OPEN_READ | ZipFile.OPEN_DELETE ))
+ {
+ doTest0(zip, zf);
+ }
+ Path p = Paths.get(name);
+ if (Files.exists(p)) {
+ fail("Failed to delete " + name + " with OPEN_DELETE");
+ }
+ }
+
+ // test scenario:
+ // (1) keep a ZipFile(zip1) alive (in ZipFile's cache), dont close it
+ // (2) delete zip1 and create zip2 with the same name the zip1 with zip2
+ // (3) zip1 tests should fail, but no crash
+ // (4) zip2 tasks should all get zip2, then pass normal testing.
+ static void testCachedDelete() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+
+ try (ZipFile zf = new ZipFile(zip1.name)) {
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> verifyNoCrash(zip1));
+ }
+ // delete the "zip1" and create a new one to test
+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ /*
+ System.out.println("========================================");
+ System.out.printf(" zip1=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n",
+ zip1.name, zip1.lastModified, zip1.entries.size(),
+ zip1.attrs.fileKey(), zip1.attrs.size(), zip1.attrs.lastModifiedTime().toMillis());
+ System.out.printf(" zip2=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n",
+ zip2.name, zip2.lastModified, zip2.entries.size(),
+ zip2.attrs.fileKey(), zip2.attrs.size(), zip2.attrs.lastModifiedTime().toMillis());
+ */
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip2));
+ }
+ }
+ }
+
+ // overwrite the "zip1" and create a new one to test. So the two zip files
+ // have the same fileKey, but probably different lastModified()
+ static void testCachedOverwrite() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ try (ZipFile zf = new ZipFile(zip1.name)) {
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> verifyNoCrash(zip1));
+ }
+ // overwrite the "zip1" with new contents
+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, false);
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip2));
+ }
+ }
+ }
+
+ // just check the entries and contents. since the file has been either overwritten
+ // or deleted/rewritten, we only care if it crahes or not.
+ static void verifyNoCrash(Zip zip) throws RuntimeException {
+ try (ZipFile zf = new ZipFile(zip.name)) {
+ List<ZipEntry> zlist = new ArrayList(zip.entries.keySet());
+ String[] elist = zf.stream().map( e -> e.getName()).toArray(String[]::new);
+ if (!Arrays.equals(elist,
+ zlist.stream().map( e -> e.getName()).toArray(String[]::new)))
+ {
+ //System.out.printf("++++++ LIST NG [%s] entries.len=%d, expected=%d+++++++%n",
+ // zf.getName(), elist.length, zlist.size());
+ return;
+ }
+ for (ZipEntry ze : zlist) {
+ byte[] zdata = zip.entries.get(ze);
+ ZipEntry e = zf.getEntry(ze.getName());
+ if (e != null) {
+ checkEqual(e, ze);
+ if (!e.isDirectory()) {
+ // check with readAllBytes
+ try (InputStream is = zf.getInputStream(e)) {
+ if (!Arrays.equals(zdata, is.readAllBytes())) {
+ //System.out.printf("++++++ BYTES NG [%s]/[%s] ++++++++%n",
+ // zf.getName(), ze.getName());
+ }
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ // t.printStackTrace();
+ // fail(t.toString());
+ }
+ }
+
+ static void checkEqual(ZipEntry x, ZipEntry y) {
+ if (x.getName().equals(y.getName()) &&
+ x.isDirectory() == y.isDirectory() &&
+ x.getMethod() == y.getMethod() &&
+ (x.getTime() / 2000) == y.getTime() / 2000 &&
+ x.getSize() == y.getSize() &&
+ x.getCompressedSize() == y.getCompressedSize() &&
+ x.getCrc() == y.getCrc() &&
+ x.getComment().equals(y.getComment())
+ ) {
+ pass();
+ } else {
+ fail(x + " not equal to " + y);
+ System.out.printf(" %s %s%n", x.getName(), y.getName());
+ System.out.printf(" %d %d%n", x.getMethod(), y.getMethod());
+ System.out.printf(" %d %d%n", x.getTime(), y.getTime());
+ System.out.printf(" %d %d%n", x.getSize(), y.getSize());
+ System.out.printf(" %d %d%n", x.getCompressedSize(), y.getCompressedSize());
+ System.out.printf(" %d %d%n", x.getCrc(), y.getCrc());
+ System.out.println("-----------------");
+ }
+ }
+
+ static void doTest(Zip zip) throws RuntimeException {
+ //Thread me = Thread.currentThread();
+ try (ZipFile zf = new ZipFile(zip.name)) {
+ doTest0(zip, zf);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ static void doTest0(Zip zip, ZipFile zf) throws Throwable {
+ List<ZipEntry> list = new ArrayList(zip.entries.keySet());
+ // (1) check entry list, in expected order
+ if (!check(Arrays.equals(
+ list.stream().map( e -> e.getName()).toArray(String[]::new),
+ zf.stream().map( e -> e.getName()).toArray(String[]::new)))) {
+ return;
+ }
+ // (2) shuffle, and check each entry and its bytes
+ Collections.shuffle(list);
+ for (ZipEntry ze : list) {
+ byte[] data = zip.entries.get(ze);
+ ZipEntry e = zf.getEntry(ze.getName());
+ checkEqual(e, ze);
+ if (!e.isDirectory()) {
+ // check with readAllBytes
+ try (InputStream is = zf.getInputStream(e)) {
+ check(Arrays.equals(data, is.readAllBytes()));
+ }
+ // check with smaller sized buf
+ try (InputStream is = zf.getInputStream(e)) {
+ byte[] buf = new byte[(int)e.getSize()];
+ int sz = r.nextInt((int)e.getSize()/4 + 1) + 1;
+ int off = 0;
+ int n;
+ while ((n = is.read(buf, off, buf.length - off)) > 0) {
+ off += n;
+ }
+ check(is.read() == -1);
+ check(Arrays.equals(data, buf));
+ }
+ }
+ }
+ // (3) check getMetaInfEntryNames
+ String[] metas = list.stream()
+ .map( e -> e.getName())
+ .filter( s -> s.startsWith("META-INF/"))
+ .sorted()
+ .toArray(String[]::new);
+ if (metas.length > 0) {
+ // meta-inf entries
+ Method getMetas = ZipFile.class.getDeclaredMethod("getMetaInfEntryNames");
+ getMetas.setAccessible(true);
+ String[] names = (String[])getMetas.invoke(zf);
+ if (names == null) {
+ fail("Failed to get metanames from " + zf);
+ } else {
+ Arrays.sort(names);
+ check(Arrays.equals(names, metas));
+ }
+ }
+ }
+
+ private static class Zip {
+ String name;
+ Map<ZipEntry, byte[]> entries;
+ BasicFileAttributes attrs;
+ long lastModified;
+
+ Zip(String name, int num, int szMax, boolean prefix, boolean clean) {
+ this.name = name;
+ entries = new LinkedHashMap<>(num);
+ try {
+ Path p = Paths.get(name);
+ if (clean) {
+ Files.deleteIfExists(p);
+ }
+ paths.add(p);
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+
+ try (FileOutputStream fos = new FileOutputStream(name);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ ZipOutputStream zos = new ZipOutputStream(bos))
+ {
+ if (prefix) {
+ byte[] bytes = new byte[r.nextInt(1000)];
+ r.nextBytes(bytes);
+ bos.write(bytes);
+ }
+ CRC32 crc = new CRC32();
+ for (int i = 0; i < num; i++) {
+ String ename = "entry-" + i + "-name-" + r.nextLong();
+ ZipEntry ze = new ZipEntry(ename);
+ int method = r.nextBoolean() ? ZipEntry.STORED : ZipEntry.DEFLATED;
+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
+ }
+ // add some manifest entries
+ for (int i = 0; i < r.nextInt(20); i++) {
+ String meta = "META-INF/" + "entry-" + i + "-metainf-" + r.nextLong();
+ ZipEntry ze = new ZipEntry(meta);
+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
+ }
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+ try {
+ this.attrs = Files.readAttributes(Paths.get(name), BasicFileAttributes.class);
+ this.lastModified = new File(name).lastModified();
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+ }
+
+ private void writeEntry(ZipOutputStream zos, CRC32 crc,
+ ZipEntry ze, int method, int szMax)
+ throws IOException
+ {
+ ze.setMethod(method);
+ byte[] data = new byte[r.nextInt(szMax + 1)];
+ r.nextBytes(data);
+ if (method == ZipEntry.STORED) { // must set size/csize/crc
+ ze.setSize(data.length);
+ ze.setCompressedSize(data.length);
+ crc.reset();
+ crc.update(data);
+ ze.setCrc(crc.getValue());
+ }
+ ze.setTime(System.currentTimeMillis());
+ ze.setComment(ze.getName());
+ zos.putNextEntry(ze);
+ zos.write(data);
+ zos.closeEntry();
+ entries.put(ze, data);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void pass(String msg) {System.out.println(msg); passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String msg) {System.out.println(msg); fail();}
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ static void unexpected(Throwable t, String msg) {
+ System.out.println(msg); failed++; t.printStackTrace();}
+ static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
+
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.println("\nPassed = " + passed + " failed = " + failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Thu Dec 17 20:27:37 2015 -0800
@@ -28,6 +28,7 @@
* @test
* @bug 8043758
* @summary Datagram Transport Layer Security (DTLS)
+ * @modules java.base/sun.security.util
* @run main/othervm DTLSOverDatagram
*/
@@ -40,7 +41,7 @@
import javax.net.ssl.*;
import java.util.concurrent.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* An example to show the way to use SSLEngine in datagram connections.
--- a/jdk/test/javax/net/ssl/templates/SSLExplorer.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/javax/net/ssl/templates/SSLExplorer.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,8 +29,6 @@
import javax.net.ssl.*;
import java.util.*;
-import sun.misc.HexDumpEncoder;
-
/**
* Instances of this class acts as an explorer of the network data of an
* SSL/TLS connection.
--- a/jdk/test/javax/print/PrintSEUmlauts/PrintSEUmlauts.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/javax/print/PrintSEUmlauts/PrintSEUmlauts.java Thu Dec 17 20:27:37 2015 -0800
@@ -107,14 +107,14 @@
System.err.println("printing content");
System.err.println(content);
}
- throw new RuntimeException("Expected <e4> to represent 'ä' but not found!");
+ throw new RuntimeException("Expected <e4> to represent '\u00e4' but not found!");
}
System.err.println("SUCCESS");
}
public int print(Graphics g, PageFormat pf, int pg) {
if (pg > 0) return NO_SUCH_PAGE;
- g.drawString("ä", 100, 100);
+ g.drawString("\u00e4", 100, 100);
return PAGE_EXISTS;
}
}
--- a/jdk/test/javax/security/auth/Subject/Subject.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/javax/security/auth/Subject/Subject.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,7 +29,6 @@
*/
package jjjjj.security.auth;
-import sun.misc.HexDumpEncoder;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.x500.X500Principal;
@@ -107,7 +106,6 @@
public static byte[] enc(Object obj) {
try {
- HexDumpEncoder hex = new HexDumpEncoder();
ByteArrayOutputStream bout;
bout = new ByteArrayOutputStream();
new ObjectOutputStream(bout).writeObject(obj);
--- a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Thu Dec 17 20:27:37 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -33,8 +33,6 @@
import java.net.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
-import java.security.Policy;
-import java.security.URIParameter;
import java.util.ArrayList;
import java.util.Collections;
import javax.xml.crypto.dsig.*;
@@ -115,10 +113,8 @@
// the policy only grants this test SocketPermission to accept, resolve
// and connect to localhost so that it can dereference 2nd reference
- URI policyURI =
- new File(System.getProperty("test.src", "."), "policy").toURI();
- Policy.setPolicy
- (Policy.getInstance("JavaPolicy", new URIParameter(policyURI)));
+ System.setProperty("java.security.policy",
+ System.getProperty("test.src", ".") + File.separator + "policy");
System.setSecurityManager(new SecurityManager());
try {
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java Thu Dec 17 20:27:37 2015 -0800
@@ -42,7 +42,11 @@
* multiple times, then the line number won't provide enough context to
* understand the failure.
* </pre>
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public class Asserts {
/**
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java Thu Dec 17 20:27:37 2015 -0800
@@ -27,6 +27,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
+ */
+@Deprecated
public final class JDKToolFinder {
private JDKToolFinder() {
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Thu Dec 17 20:27:37 2015 -0800
@@ -46,7 +46,10 @@
* Process p = pb.start();
* }
* </pre>
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public class JDKToolLauncher {
private final String executable;
private final List<String> vmArgs = new ArrayList<String>();
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,12 @@
/**
* Utility class for verifying output and exit value from a {@code Process}.
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ *
*/
+@Deprecated
public final class OutputAnalyzer {
private final OutputBuffer output;
private final String stdout;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java Thu Dec 17 20:27:37 2015 -0800
@@ -28,6 +28,11 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
class OutputBuffer {
private static class OutputBufferException extends RuntimeException {
private static final long serialVersionUID = 8528687792643129571L;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java Thu Dec 17 20:27:37 2015 -0800
@@ -27,6 +27,11 @@
import java.io.FileNotFoundException;
import java.io.IOException;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
+ */
+@Deprecated
public class Platform {
private static final String osName = System.getProperty("os.name");
private static final String dataModel = System.getProperty("sun.arch.data.model");
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Thu Dec 17 20:27:37 2015 -0800
@@ -27,8 +27,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -42,6 +40,12 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
+
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
public final class ProcessTools {
private static final class LineForwarder extends StreamPumper.LinePump {
private final PrintStream ps;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java Thu Dec 17 20:27:37 2015 -0800
@@ -34,6 +34,11 @@
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
public final class StreamPumper implements Runnable {
private static final int BUF_SIZE = 256;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Thu Dec 17 20:27:37 2015 -0800
@@ -41,7 +41,11 @@
/**
* Common library for various test helper functions.
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public final class Utils {
/**
--- a/jdk/test/sun/misc/Encode/DecodeBuffer.java Wed Jul 05 21:08:30 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4159554
- * @summary Problem with UUDecoder
- * @modules java.base/sun.misc
- */
-
-import sun.misc.*;
-import java.io.*;
-
-public class DecodeBuffer {
-
- public static void main(String[] args) throws Exception {
- String encoded;
- // text to encode and decode
- String originalText = "Hi There, please encode and decode me";
- UUDecoder uuD = new UUDecoder();
-
- encoded = "begin 644 encoder.buf\r\n" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\r\n"+
- " \r\nend\r\n";
- check (uuD, encoded, originalText);
-
- encoded = "begin 644 encoder.buf\n" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\n"+
- " \nend\n";
- check (uuD, encoded, originalText);
-
- encoded = "begin 644 encoder.buf\r" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\r"+
- " \rend\r";
- check (uuD, encoded, originalText);
-
- // Multi-line Unix text file
-
- String s1 = "begin 644 f\n"+
- "M3W)I9VYL(\"I(:2!4:&5R92P@<&QE87-E(&5N8V]D92!A;F0@9&5C;V1E(&UE\n"+
- "M*@IA;F0@;64@06YD($UE(&%N1\"!M92!!;F0@344@04Y$($U%(%I80U8@,3(S\n"+
- "-97)T\"E5)3U @45=%\"DUE\n"+
- " \nend\n";
-
- String s2 = "Orignl *Hi There, please encode and decode me*\n"+
- "and me And Me anD me And ME AND ME ZXCV 123ert\n"+
- "UIOP QWE\n";
- check (uuD, s1, s2);
-
- // Multi-line Windows text file
-
- s1 = "begin 644 f\n"+
- "M2&5L;&\\@22!A;2!A(&UU;'1I;&EN92!F:6QE#0IC<F5A=&5D(&]N(%=I;F1O\r\n"+
- "M=W,L('1O('1E<W0@=&AE(%5516YC;V1E<@T*86YD(%551&5C;V1E<B!C;&%S\r\n"+
- "$<V5S+G1O\r\n"+ " \r\nend\r\n";
- s2="Hello I am a multiline file\r\n"+
- "created on Windows, to test the UUEncoder\r\n"+
- "and UUDecoder classes.";
- check (uuD, s1, s2);
- }
-
- public static void check (UUDecoder uuD, String s, String original) throws Exception {
- String decoded;
- // do UU stuff
- decoded = new String(uuD.decodeBuffer(s));
- if (!decoded.equals (original)) {
- throw new Exception ("decoded text not same as original");
- }
- }
-}
--- a/jdk/test/sun/misc/Encode/Encode.java Wed Jul 05 21:08:30 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4041231
- * @summary Test UUEncoder.java for proper masking in encodeAtom
- * @modules java.base/sun.misc
- */
-
-import sun.misc.*;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-public class Encode {
-
- public static void main(String[] args) throws Exception {
- UUEncoder encoder = new UUEncoder("encode.buf");
- byte[] buffer = new byte[3];
-
- buffer[0] = -1;
- buffer[1] = -1;
- buffer[2] = -1;
-
- ByteArrayInputStream in = new ByteArrayInputStream(buffer);
- ByteArrayOutputStream out = new ByteArrayOutputStream(10);
-
- encoder.encodeBuffer(in, out);
- byte[] result = out.toByteArray();
-
- if (result[22] == 31)
- throw new RuntimeException("UUEncoder generates incorrect byte sequences in encodeAtom.");
-
- }
-}
--- a/jdk/test/sun/misc/Encode/GetBytes.java Wed Jul 05 21:08:30 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 5031097
- * @summary sun.misc.CharacterEncoder(ByteBuffer) is dumping too
- * much information
- * @modules java.base/sun.misc
- * @author Brad Wetmore
- */
-
-import java.nio.*;
-import sun.misc.*;
-
-public class GetBytes {
-
- public static void main(String args[]) throws Exception {
-
- ByteBuffer bb = ByteBuffer.wrap(new byte [26 + 2]);
-
- for (int i = 'a'; i < 'a' + bb.capacity(); i++) {
- bb.put((byte)i);
- }
-
- /*
- * Slice a subbuffer out of the original buffer.
- */
- bb.position(1);
- bb.limit(bb.capacity() - 1);
-
- ByteBuffer src = bb.slice();
-
- CharacterEncoder e = new BASE64Encoder();
- CharacterDecoder d = new BASE64Decoder();
-
- String encoded = e.encodeBuffer(src);
- ByteBuffer dst = d.decodeBufferToByteBuffer(encoded);
-
- src.rewind();
- dst.rewind();
-
- if (src.compareTo(dst) != 0) {
- throw new Exception("Didn't encode/decode correctly");
- }
- }
-}
--- a/jdk/test/sun/security/krb5/auto/MSOID2.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/MSOID2.java Thu Dec 17 20:27:37 2015 -0800
@@ -30,6 +30,7 @@
*/
import sun.security.jgss.GSSUtil;
+import sun.security.util.HexDumpEncoder;
// The basic krb5 test skeleton you can copy from
public class MSOID2 {
@@ -69,7 +70,7 @@
nt[pos] = (byte)newLen;
}
t = nt;
- new sun.misc.HexDumpEncoder().encodeBuffer(t, System.out);
+ new HexDumpEncoder().encodeBuffer(t, System.out);
}
if (t != null || !s.x().isEstablished()) t = s.take(t);
if (c.x().isEstablished() && s.x().isEstablished()) break;
--- a/jdk/test/sun/security/mscapi/PublicKeyInterop.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.java Thu Dec 17 20:27:37 2015 -0800
@@ -29,7 +29,7 @@
import java.util.*;
import javax.crypto.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/*
* Confirm interoperability of RSA public keys between SunMSCAPI and SunJCE
--- a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Thu Dec 17 20:27:37 2015 -0800
@@ -25,6 +25,7 @@
# @test
# @bug 6888925
+# @modules java.base/sun.security.util
# @requires os.family == "windows"
# @run shell PublicKeyInterop.sh
# @summary SunMSCAPI's Cipher can't use RSA public keys obtained from other
--- a/jdk/test/sun/security/pkcs/pkcs7/SignerOrder.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/pkcs/pkcs7/SignerOrder.java Thu Dec 17 20:27:37 2015 -0800
@@ -40,7 +40,7 @@
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Date;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
--- a/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java Thu Dec 17 20:27:37 2015 -0800
@@ -43,7 +43,7 @@
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS8Key;
import sun.security.provider.DSAPrivateKey;
import sun.security.util.DerOutputStream;
--- a/jdk/test/sun/security/pkcs/pkcs9/UnknownAttribute.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/pkcs/pkcs9/UnknownAttribute.java Thu Dec 17 20:27:37 2015 -0800
@@ -33,7 +33,7 @@
import java.io.*;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS9Attribute;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
--- a/jdk/test/sun/security/x509/X500Name/NullX500Name.java Wed Jul 05 21:08:30 2017 +0200
+++ b/jdk/test/sun/security/x509/X500Name/NullX500Name.java Thu Dec 17 20:27:37 2015 -0800
@@ -32,7 +32,7 @@
import java.util.Arrays;
import sun.security.util.DerOutputStream;
import sun.security.x509.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
public class NullX500Name {