Merge
diff --git a/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java
index be0204e..9f1204c 100644
--- a/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java
+++ b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java
@@ -618,6 +618,11 @@
// remove ROC, which is not supported in j.u.tz
builtZones.remove("ROC");
links.remove("ROC");
+ // remove EST, HST and MST. They are supported via
+ // the short-id mapping
+ builtZones.remove("EST");
+ builtZones.remove("HST");
+ builtZones.remove("MST");
}
/**
diff --git a/makefiles/Setup.gmk b/makefiles/Setup.gmk
index b624afb..d2e706f 100644
--- a/makefiles/Setup.gmk
+++ b/makefiles/Setup.gmk
@@ -27,7 +27,7 @@
# To build with all warnings enabled, do the following:
# make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000"
-JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,classfile,dep-ann,divzero,varargs -Werror
+JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,classfile,dep-ann,divzero,empty,try,varargs -Werror
# Any java code executed during a JDK build to build other parts of the JDK must be
# executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this
diff --git a/makefiles/mapfiles/libjava/mapfile-vers b/makefiles/mapfiles/libjava/mapfile-vers
index 29ce7eb..7b4d547 100644
--- a/makefiles/mapfiles/libjava/mapfile-vers
+++ b/makefiles/mapfiles/libjava/mapfile-vers
@@ -267,7 +267,8 @@
Java_sun_misc_GC_maxObjectInspectionAge;
Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
Java_sun_reflect_NativeMethodAccessorImpl_invoke0;
- Java_sun_reflect_Reflection_getCallerClass;
+ Java_sun_reflect_Reflection_getCallerClass__;
+ Java_sun_reflect_Reflection_getCallerClass__I;
Java_sun_reflect_Reflection_getClassAccessFlags;
Java_sun_misc_Version_getJdkVersionInfo;
Java_sun_misc_Version_getJdkSpecialVersion;
diff --git a/makefiles/mapfiles/libjava/reorder-sparc b/makefiles/mapfiles/libjava/reorder-sparc
index b64537e..1657305 100644
--- a/makefiles/mapfiles/libjava/reorder-sparc
+++ b/makefiles/mapfiles/libjava/reorder-sparc
@@ -27,7 +27,8 @@
text: .text%Java_java_io_FileDescriptor_initIDs;
text: .text%Java_java_io_FileOutputStream_initIDs;
text: .text%Java_java_lang_System_setIn0;
-text: .text%Java_sun_reflect_Reflection_getCallerClass;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
text: .text%Java_java_lang_Class_forName0;
text: .text%Java_java_lang_Object_getClass;
text: .text%Java_sun_reflect_Reflection_getClassAccessFlags;
diff --git a/makefiles/mapfiles/libjava/reorder-sparcv9 b/makefiles/mapfiles/libjava/reorder-sparcv9
index 8e6d249..fe80fca 100644
--- a/makefiles/mapfiles/libjava/reorder-sparcv9
+++ b/makefiles/mapfiles/libjava/reorder-sparcv9
@@ -26,7 +26,8 @@
text: .text%Java_java_io_FileDescriptor_initIDs;
text: .text%Java_java_io_FileOutputStream_initIDs;
text: .text%Java_java_lang_System_setIn0;
-text: .text%Java_sun_reflect_Reflection_getCallerClass;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
text: .text%Java_java_lang_Class_forName0;
text: .text%Java_java_lang_String_intern;
text: .text%Java_java_lang_Float_floatToIntBits;
diff --git a/makefiles/mapfiles/libjava/reorder-x86 b/makefiles/mapfiles/libjava/reorder-x86
index ff4836f..839ee50 100644
--- a/makefiles/mapfiles/libjava/reorder-x86
+++ b/makefiles/mapfiles/libjava/reorder-x86
@@ -28,7 +28,8 @@
text: .text%Java_java_io_FileDescriptor_initIDs;
text: .text%Java_java_io_FileOutputStream_initIDs;
text: .text%Java_java_lang_System_setIn0;
-text: .text%Java_sun_reflect_Reflection_getCallerClass;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__;
+text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
text: .text%Java_java_lang_Class_forName0;
text: .text%Java_java_lang_String_intern;
text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
diff --git a/src/share/back/ThreadGroupReferenceImpl.c b/src/share/back/ThreadGroupReferenceImpl.c
index 06ae010..47b894a 100644
--- a/src/share/back/ThreadGroupReferenceImpl.c
+++ b/src/share/back/ThreadGroupReferenceImpl.c
@@ -47,7 +47,7 @@
(void)memset(&info, 0, sizeof(info));
threadGroupInfo(group, &info);
- (void)outStream_writeString(out, info.name);
+ (void)outStream_writeString(out, info.name == NULL ? "" : info.name);
if ( info.name != NULL )
jvmtiDeallocate(info.name);
diff --git a/src/share/back/outStream.c b/src/share/back/outStream.c
index 8eeebc4..b48d559 100644
--- a/src/share/back/outStream.c
+++ b/src/share/back/outStream.c
@@ -298,17 +298,15 @@
outStream_writeString(PacketOutputStream *stream, char *string)
{
jdwpError error;
- jint length;
+ jint length = string != NULL ? (int)strlen(string) : 0;
/* Options utf8=y/n controls if we want Standard UTF-8 or Modified */
if ( gdata->modifiedUtf8 ) {
- length = (int)strlen(string);
(void)outStream_writeInt(stream, length);
error = writeBytes(stream, (jbyte *)string, length);
} else {
jint new_length;
- length = (int)strlen(string);
new_length = (gdata->npt->utf8mToUtf8sLength)
(gdata->npt->utf, (jbyte*)string, length);
if ( new_length == length ) {
diff --git a/src/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties b/src/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties
index c4eeded..a8985ce 100644
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties
@@ -41,7 +41,7 @@
FileChooser.openDialogTitle.textAndMnemonic=\u00D6ffnen
FileChooser.pathLabel.textAndMnemonic=Aus&wahl:
FileChooser.filterLabel.textAndMnemonic=Filter:
-FileChooser.foldersLabel.textAndMnemonic=Or&dner
+FileChooser.foldersLabel.textAndMnemonic=O&rdner
FileChooser.filesLabel.textAndMnemonic=&Dateien
FileChooser.cancelButtonToolTip.textAndMnemonic=Dialogfeld f\u00FCr Dateiauswahl schlie\u00DFen.
diff --git a/src/share/classes/com/sun/jmx/snmp/SnmpString.java b/src/share/classes/com/sun/jmx/snmp/SnmpString.java
index 9ec7f7c..76af600 100644
--- a/src/share/classes/com/sun/jmx/snmp/SnmpString.java
+++ b/src/share/classes/com/sun/jmx/snmp/SnmpString.java
@@ -130,7 +130,7 @@
* @return The value.
*/
public byte[] byteValue() {
- return value ;
+ return value.clone() ;
}
/**
diff --git a/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java b/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java
index df75874..ac9c4bb 100644
--- a/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java
+++ b/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java
@@ -476,8 +476,7 @@
rootOid[i++]= val.longValue();
}
}
- return rootOid;
-
+ return rootOid.clone();
}
// --------------------------------------------------------------------
diff --git a/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java b/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java
index b2634d8..b0828e2 100644
--- a/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java
+++ b/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java
@@ -1248,7 +1248,7 @@
"of this CommunicatorServer instance has changed.");
}
- return notifInfos;
+ return notifInfos.clone();
}
/**
diff --git a/src/share/classes/java/io/ByteArrayInputStream.java b/src/share/classes/java/io/ByteArrayInputStream.java
index e58c6e6..ce0b8d1 100644
--- a/src/share/classes/java/io/ByteArrayInputStream.java
+++ b/src/share/classes/java/io/ByteArrayInputStream.java
@@ -275,7 +275,6 @@
* Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
- * <p>
*/
public void close() throws IOException {
}
diff --git a/src/share/classes/java/io/ByteArrayOutputStream.java b/src/share/classes/java/io/ByteArrayOutputStream.java
index d28d397..cd3c139 100644
--- a/src/share/classes/java/io/ByteArrayOutputStream.java
+++ b/src/share/classes/java/io/ByteArrayOutputStream.java
@@ -263,8 +263,6 @@
* Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
- * <p>
- *
*/
public void close() throws IOException {
}
diff --git a/src/share/classes/java/io/Closeable.java b/src/share/classes/java/io/Closeable.java
index 530cde8..b4a1c81 100644
--- a/src/share/classes/java/io/Closeable.java
+++ b/src/share/classes/java/io/Closeable.java
@@ -34,7 +34,6 @@
*
* @since 1.5
*/
-@FunctionalInterface
public interface Closeable extends AutoCloseable {
/**
diff --git a/src/share/classes/java/io/DataInput.java b/src/share/classes/java/io/DataInput.java
index 58a3a2b..c61aeb5 100644
--- a/src/share/classes/java/io/DataInput.java
+++ b/src/share/classes/java/io/DataInput.java
@@ -155,7 +155,7 @@
* to the length of {@code b}.
* <p>
* This method blocks until one of the
- * following conditions occurs:<p>
+ * following conditions occurs:
* <ul>
* <li>{@code b.length}
* bytes of input data are available, in which
@@ -197,7 +197,7 @@
* <p>
* This method
* blocks until one of the following conditions
- * occurs:<p>
+ * occurs:
* <ul>
* <li>{@code len} bytes
* of input data are available, in which case
@@ -316,8 +316,8 @@
* be the second byte. The value
* returned
* is:
- * <p><pre><code>(short)((a << 8) | (b & 0xff))
- * </code></pre>
+ * <pre>{@code (short)((a << 8) | (b & 0xff))
+ * }</pre>
* This method
* is suitable for reading the bytes written
* by the {@code writeShort} method of
@@ -337,8 +337,8 @@
* be the first byte read and
* {@code b}
* be the second byte. The value returned is:
- * <p><pre><code>(((a & 0xff) << 8) | (b & 0xff))
- * </code></pre>
+ * <pre>{@code (((a & 0xff) << 8) | (b & 0xff))
+ * }</pre>
* This method is suitable for reading the bytes
* written by the {@code writeShort} method
* of interface {@code DataOutput} if
@@ -359,8 +359,8 @@
* be the first byte read and {@code b}
* be the second byte. The value
* returned is:
- * <p><pre><code>(char)((a << 8) | (b & 0xff))
- * </code></pre>
+ * <pre>{@code (char)((a << 8) | (b & 0xff))
+ * }</pre>
* This method
* is suitable for reading bytes written by
* the {@code writeChar} method of interface
@@ -377,10 +377,10 @@
* Reads four input bytes and returns an
* {@code int} value. Let {@code a-d}
* be the first through fourth bytes read. The value returned is:
- * <p><pre><code>
- * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
- *  ((c & 0xff) << 8) | (d & 0xff))
- * </code></pre>
+ * <pre>{@code
+ * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
+ * ((c & 0xff) << 8) | (d & 0xff))
+ * }</pre>
* This method is suitable
* for reading bytes written by the {@code writeInt}
* method of interface {@code DataOutput}.
@@ -397,16 +397,16 @@
* a {@code long} value. Let {@code a-h}
* be the first through eighth bytes read.
* The value returned is:
- * <p><pre><code>
- * (((long)(a & 0xff) << 56) |
- * ((long)(b & 0xff) << 48) |
- * ((long)(c & 0xff) << 40) |
- * ((long)(d & 0xff) << 32) |
- * ((long)(e & 0xff) << 24) |
- * ((long)(f & 0xff) << 16) |
- * ((long)(g & 0xff) << 8) |
- * ((long)(h & 0xff)))
- * </code></pre>
+ * <pre>{@code
+ * (((long)(a & 0xff) << 56) |
+ * ((long)(b & 0xff) << 48) |
+ * ((long)(c & 0xff) << 40) |
+ * ((long)(d & 0xff) << 32) |
+ * ((long)(e & 0xff) << 24) |
+ * ((long)(f & 0xff) << 16) |
+ * ((long)(g & 0xff) << 8) |
+ * ((long)(h & 0xff)))
+ * }</pre>
* <p>
* This method is suitable
* for reading bytes written by the {@code writeLong}
@@ -540,9 +540,9 @@
* not match the bit pattern {@code 10xxxxxx},
* then a {@code UTFDataFormatException}
* is thrown. Otherwise, the group is converted
- * to the character:<p>
- * <pre><code>(char)(((a& 0x1F) << 6) | (b & 0x3F))
- * </code></pre>
+ * to the character:
+ * <pre>{@code (char)(((a & 0x1F) << 6) | (b & 0x3F))
+ * }</pre>
* If the first byte of a group
* matches the bit pattern {@code 1110xxxx},
* then the group consists of that byte {@code a}
@@ -554,10 +554,10 @@
* does not match the bit pattern {@code 10xxxxxx},
* then a {@code UTFDataFormatException}
* is thrown. Otherwise, the group is converted
- * to the character:<p>
- * <pre><code>
- * (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F))
- * </code></pre>
+ * to the character:
+ * <pre>{@code
+ * (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F))
+ * }</pre>
* If the first byte of a group matches the
* pattern {@code 1111xxxx} or the pattern
* {@code 10xxxxxx}, then a {@code UTFDataFormatException}
diff --git a/src/share/classes/java/io/DataOutput.java b/src/share/classes/java/io/DataOutput.java
index 07fbc3a..ce909d1 100644
--- a/src/share/classes/java/io/DataOutput.java
+++ b/src/share/classes/java/io/DataOutput.java
@@ -134,11 +134,11 @@
* Writes two bytes to the output
* stream to represent the value of the argument.
* The byte values to be written, in the order
- * shown, are: <p>
- * <pre><code>
- * (byte)(0xff & (v >> 8))
- * (byte)(0xff & v)
- * </code> </pre> <p>
+ * shown, are:
+ * <pre>{@code
+ * (byte)(0xff & (v >> 8))
+ * (byte)(0xff & v)
+ * }</pre> <p>
* The bytes written by this method may be
* read by the <code>readShort</code> method
* of interface <code>DataInput</code> , which
@@ -156,10 +156,10 @@
* output stream.
* The byte values to be written, in the order
* shown, are:
- * <p><pre><code>
- * (byte)(0xff & (v >> 8))
- * (byte)(0xff & v)
- * </code></pre><p>
+ * <pre>{@code
+ * (byte)(0xff & (v >> 8))
+ * (byte)(0xff & v)
+ * }</pre><p>
* The bytes written by this method may be
* read by the <code>readChar</code> method
* of interface <code>DataInput</code> , which
@@ -176,12 +176,12 @@
* comprised of four bytes, to the output stream.
* The byte values to be written, in the order
* shown, are:
- * <p><pre><code>
- * (byte)(0xff & (v >> 24))
- * (byte)(0xff & (v >> 16))
- * (byte)(0xff & (v >>    8))
- * (byte)(0xff & v)
- * </code></pre><p>
+ * <pre>{@code
+ * (byte)(0xff & (v >> 24))
+ * (byte)(0xff & (v >> 16))
+ * (byte)(0xff & (v >> 8))
+ * (byte)(0xff & v)
+ * }</pre><p>
* The bytes written by this method may be read
* by the <code>readInt</code> method of interface
* <code>DataInput</code> , which will then
@@ -197,16 +197,16 @@
* comprised of eight bytes, to the output stream.
* The byte values to be written, in the order
* shown, are:
- * <p><pre><code>
- * (byte)(0xff & (v >> 56))
- * (byte)(0xff & (v >> 48))
- * (byte)(0xff & (v >> 40))
- * (byte)(0xff & (v >> 32))
- * (byte)(0xff & (v >> 24))
- * (byte)(0xff & (v >> 16))
- * (byte)(0xff & (v >> 8))
- * (byte)(0xff & v)
- * </code></pre><p>
+ * <pre>{@code
+ * (byte)(0xff & (v >> 56))
+ * (byte)(0xff & (v >> 48))
+ * (byte)(0xff & (v >> 40))
+ * (byte)(0xff & (v >> 32))
+ * (byte)(0xff & (v >> 24))
+ * (byte)(0xff & (v >> 16))
+ * (byte)(0xff & (v >> 8))
+ * (byte)(0xff & v)
+ * }</pre><p>
* The bytes written by this method may be
* read by the <code>readLong</code> method
* of interface <code>DataInput</code> , which
@@ -314,24 +314,24 @@
* If a character <code>c</code>
* is in the range <code>\u0001</code> through
* <code>\u007f</code>, it is represented
- * by one byte:<p>
+ * by one byte:
* <pre>(byte)c </pre> <p>
* If a character <code>c</code> is <code>\u0000</code>
* or is in the range <code>\u0080</code>
* through <code>\u07ff</code>, then it is
* represented by two bytes, to be written
- * in the order shown:<p> <pre><code>
- * (byte)(0xc0 | (0x1f & (c >> 6)))
- * (byte)(0x80 | (0x3f & c))
- * </code></pre> <p> If a character
+ * in the order shown: <pre>{@code
+ * (byte)(0xc0 | (0x1f & (c >> 6)))
+ * (byte)(0x80 | (0x3f & c))
+ * }</pre> <p> If a character
* <code>c</code> is in the range <code>\u0800</code>
* through <code>uffff</code>, then it is
* represented by three bytes, to be written
- * in the order shown:<p> <pre><code>
- * (byte)(0xe0 | (0x0f & (c >> 12)))
- * (byte)(0x80 | (0x3f & (c >> 6)))
- * (byte)(0x80 | (0x3f & c))
- * </code></pre> <p> First,
+ * in the order shown: <pre>{@code
+ * (byte)(0xe0 | (0x0f & (c >> 12)))
+ * (byte)(0x80 | (0x3f & (c >> 6)))
+ * (byte)(0x80 | (0x3f & c))
+ * }</pre> <p> First,
* the total number of bytes needed to represent
* all the characters of <code>s</code> is
* calculated. If this number is larger than
diff --git a/src/share/classes/java/io/FilePermission.java b/src/share/classes/java/io/FilePermission.java
index e70d292..89f2c33 100644
--- a/src/share/classes/java/io/FilePermission.java
+++ b/src/share/classes/java/io/FilePermission.java
@@ -55,7 +55,7 @@
* a list of one or more comma-separated keywords. The possible keywords are
* "read", "write", "execute", "delete", and "readlink". Their meaning is
* defined as follows:
- * <P>
+ *
* <DL>
* <DT> read <DD> read permission
* <DT> write <DD> write permission
@@ -297,11 +297,11 @@
/**
* Checks if this FilePermission object "implies" the specified permission.
* <P>
- * More specifically, this method returns true if:<p>
+ * More specifically, this method returns true if:
* <ul>
- * <li> <i>p</i> is an instanceof FilePermission,<p>
+ * <li> <i>p</i> is an instanceof FilePermission,
* <li> <i>p</i>'s actions are a proper subset of this
- * object's actions, and <p>
+ * object's actions, and
* <li> <i>p</i>'s pathname is implied by this object's
* pathname. For example, "/tmp/*" implies "/tmp/foo", since
* "/tmp/*" encompasses all files in the "/tmp" directory,
diff --git a/src/share/classes/java/io/Flushable.java b/src/share/classes/java/io/Flushable.java
index 8912316..fe90fbd 100644
--- a/src/share/classes/java/io/Flushable.java
+++ b/src/share/classes/java/io/Flushable.java
@@ -34,7 +34,6 @@
*
* @since 1.5
*/
-@FunctionalInterface
public interface Flushable {
/**
diff --git a/src/share/classes/java/io/InputStream.java b/src/share/classes/java/io/InputStream.java
index 3c7ff17..6c46a40 100644
--- a/src/share/classes/java/io/InputStream.java
+++ b/src/share/classes/java/io/InputStream.java
@@ -306,8 +306,7 @@
*
* <p> The general contract of <code>reset</code> is:
*
- * <p><ul>
- *
+ * <ul>
* <li> If the method <code>markSupported</code> returns
* <code>true</code>, then:
*
diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java
index c71681c..15ecd9b 100644
--- a/src/share/classes/java/io/ObjectInputStream.java
+++ b/src/share/classes/java/io/ObjectInputStream.java
@@ -109,7 +109,7 @@
*
* <p>Serializable classes that require special handling during the
* serialization and deserialization process should implement the following
- * methods:<p>
+ * methods:
*
* <pre>
* private void writeObject(java.io.ObjectOutputStream stream)
diff --git a/src/share/classes/java/io/PipedInputStream.java b/src/share/classes/java/io/PipedInputStream.java
index af07de5..83dde31 100644
--- a/src/share/classes/java/io/PipedInputStream.java
+++ b/src/share/classes/java/io/PipedInputStream.java
@@ -172,15 +172,14 @@
* unconnected piped output stream and <code>snk</code>
* is an unconnected piped input stream, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped output stream to connect to.
* @exception IOException if an I/O error occurs.
diff --git a/src/share/classes/java/io/PipedReader.java b/src/share/classes/java/io/PipedReader.java
index bb86022..3471646 100644
--- a/src/share/classes/java/io/PipedReader.java
+++ b/src/share/classes/java/io/PipedReader.java
@@ -145,15 +145,14 @@
* unconnected piped writer and <code>snk</code>
* is an unconnected piped reader, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped writer to connect to.
* @exception IOException if an I/O error occurs.
diff --git a/src/share/classes/java/io/RandomAccessFile.java b/src/share/classes/java/io/RandomAccessFile.java
index fd1c712..c48aa99 100644
--- a/src/share/classes/java/io/RandomAccessFile.java
+++ b/src/share/classes/java/io/RandomAccessFile.java
@@ -784,7 +784,7 @@
* </pre></blockquote>
* <p>
* then the result is equal to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* ((long)b1 << 56) + ((long)b2 << 48)
* + ((long)b3 << 40) + ((long)b4 << 32)
* + ((long)b5 << 24) + ((long)b6 << 16)
diff --git a/src/share/classes/java/io/Serializable.java b/src/share/classes/java/io/Serializable.java
index fc717f7..2f7bea1 100644
--- a/src/share/classes/java/io/Serializable.java
+++ b/src/share/classes/java/io/Serializable.java
@@ -55,7 +55,7 @@
*
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
- * signatures: <p>
+ * signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
@@ -101,7 +101,7 @@
*
* <p>Serializable classes that need to designate an alternative object to be
* used when writing an object to the stream should implement this
- * special method with the exact signature: <p>
+ * special method with the exact signature:
*
* <PRE>
* ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
@@ -115,7 +115,7 @@
*
* Classes that need to designate a replacement when an instance of it
* is read from the stream should implement this special method with the
- * exact signature.<p>
+ * exact signature.
*
* <PRE>
* ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
@@ -133,7 +133,7 @@
* deserialization will result in an {@link InvalidClassException}. A
* serializable class can declare its own serialVersionUID explicitly by
* declaring a field named <code>"serialVersionUID"</code> that must be static,
- * final, and of type <code>long</code>:<p>
+ * final, and of type <code>long</code>:
*
* <PRE>
* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
diff --git a/src/share/classes/java/io/SerializablePermission.java b/src/share/classes/java/io/SerializablePermission.java
index eaa2913..b208d24 100644
--- a/src/share/classes/java/io/SerializablePermission.java
+++ b/src/share/classes/java/io/SerializablePermission.java
@@ -43,7 +43,6 @@
* The following table lists all the possible SerializablePermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- * <P>
*
* <table border=1 cellpadding=5 summary="Permission target name, what the permission allows, and associated risks">
* <tr>
diff --git a/src/share/classes/java/lang/AbstractStringBuilder.java b/src/share/classes/java/lang/AbstractStringBuilder.java
index 3260da6..3cde60d 100644
--- a/src/share/classes/java/lang/AbstractStringBuilder.java
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java
@@ -330,9 +330,9 @@
* characters to be copied is {@code srcEnd-srcBegin}. The
* characters are copied into the subarray of {@code dst} starting
* at index {@code dstBegin} and ending at index:
- * <p><blockquote><pre>
+ * <pre>{@code
* dstbegin + (srcEnd-srcBegin) - 1
- * </pre></blockquote>
+ * }</pre>
*
* @param srcBegin start copying at this offset.
* @param srcEnd stop copying at this offset.
@@ -859,16 +859,16 @@
*
* <p> An invocation of this method of the form
*
- * <blockquote><pre>
- * sb.subSequence(begin, end)</pre></blockquote>
+ * <pre>{@code
+ * sb.subSequence(begin, end)}</pre>
*
* behaves in exactly the same way as the invocation
*
- * <blockquote><pre>
- * sb.substring(begin, end)</pre></blockquote>
+ * <pre>{@code
+ * sb.substring(begin, end)}</pre>
*
* This method is provided so that this class can
- * implement the {@link CharSequence} interface. </p>
+ * implement the {@link CharSequence} interface.
*
* @param start the start index, inclusive.
* @param end the end index, exclusive.
@@ -1287,9 +1287,9 @@
* Returns the index within this string of the first occurrence of the
* specified substring. The integer returned is the smallest value
* <i>k</i> such that:
- * <blockquote><pre>
+ * <pre>{@code
* this.toString().startsWith(str, <i>k</i>)
- * </pre></blockquote>
+ * }</pre>
* is {@code true}.
*
* @param str any string.
@@ -1306,10 +1306,10 @@
* Returns the index within this string of the first occurrence of the
* specified substring, starting at the specified index. The integer
* returned is the smallest value {@code k} for which:
- * <blockquote><pre>
+ * <pre>{@code
* k >= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* If no such value of <i>k</i> exists, then -1 is returned.
*
* @param str the substring for which to search.
@@ -1326,9 +1326,9 @@
* of the specified substring. The rightmost empty string "" is
* considered to occur at the index value {@code this.length()}.
* The returned index is the largest value <i>k</i> such that
- * <blockquote><pre>
+ * <pre>{@code
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* is true.
*
* @param str the substring to search for.
@@ -1345,10 +1345,10 @@
* Returns the index within this string of the last occurrence of the
* specified substring. The integer returned is the largest value <i>k</i>
* such that:
- * <blockquote><pre>
+ * <pre>{@code
* k <= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
- * </pre></blockquote>
+ * }</pre>
* If no such value of <i>k</i> exists, then -1 is returned.
*
* @param str the substring to search for.
diff --git a/src/share/classes/java/lang/ArrayStoreException.java b/src/share/classes/java/lang/ArrayStoreException.java
index aec35f2..96fa744 100644
--- a/src/share/classes/java/lang/ArrayStoreException.java
+++ b/src/share/classes/java/lang/ArrayStoreException.java
@@ -29,7 +29,7 @@
* Thrown to indicate that an attempt has been made to store the
* wrong type of object into an array of objects. For example, the
* following code generates an <code>ArrayStoreException</code>:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* Object x[] = new String[3];
* x[0] = new Integer(0);
* </pre></blockquote>
diff --git a/src/share/classes/java/lang/AutoCloseable.java b/src/share/classes/java/lang/AutoCloseable.java
index be47cd0..135d9fe 100644
--- a/src/share/classes/java/lang/AutoCloseable.java
+++ b/src/share/classes/java/lang/AutoCloseable.java
@@ -48,7 +48,6 @@
* @author Josh Bloch
* @since 1.7
*/
-@FunctionalInterface
public interface AutoCloseable {
/**
* Closes this resource, relinquishing any underlying resources.
diff --git a/src/share/classes/java/lang/Byte.java b/src/share/classes/java/lang/Byte.java
index 275e33d..3a894a5 100644
--- a/src/share/classes/java/lang/Byte.java
+++ b/src/share/classes/java/lang/Byte.java
@@ -244,7 +244,7 @@
* <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i>
- * <p>
+ *
* <dt><i>Sign:</i>
* <dd>{@code -}
* <dd>{@code +}
diff --git a/src/share/classes/java/lang/Character.java b/src/share/classes/java/lang/Character.java
index 41576cc..0926758 100644
--- a/src/share/classes/java/lang/Character.java
+++ b/src/share/classes/java/lang/Character.java
@@ -5394,7 +5394,7 @@
* Other_Lowercase as defined by the Unicode Standard.
* <p>
* The following are examples of lowercase characters:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* a b c d e f g h i j k l m n o p q r s t u v w x y z
* '\u00DF' '\u00E0' '\u00E1' '\u00E2' '\u00E3' '\u00E4' '\u00E5' '\u00E6'
* '\u00E7' '\u00E8' '\u00E9' '\u00EA' '\u00EB' '\u00EC' '\u00ED' '\u00EE'
@@ -5430,7 +5430,7 @@
* Other_Lowercase as defined by the Unicode Standard.
* <p>
* The following are examples of lowercase characters:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* a b c d e f g h i j k l m n o p q r s t u v w x y z
* '\u00DF' '\u00E0' '\u00E1' '\u00E2' '\u00E3' '\u00E4' '\u00E5' '\u00E6'
* '\u00E7' '\u00E8' '\u00E9' '\u00EA' '\u00EB' '\u00EC' '\u00ED' '\u00EE'
@@ -5461,14 +5461,14 @@
* or it has contributory property Other_Uppercase as defined by the Unicode Standard.
* <p>
* The following are examples of uppercase characters:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
* '\u00C0' '\u00C1' '\u00C2' '\u00C3' '\u00C4' '\u00C5' '\u00C6' '\u00C7'
* '\u00C8' '\u00C9' '\u00CA' '\u00CB' '\u00CC' '\u00CD' '\u00CE' '\u00CF'
* '\u00D0' '\u00D1' '\u00D2' '\u00D3' '\u00D4' '\u00D5' '\u00D6' '\u00D8'
* '\u00D9' '\u00DA' '\u00DB' '\u00DC' '\u00DD' '\u00DE'
* </pre></blockquote>
- * <p> Many other Unicode characters are uppercase too.<p>
+ * <p> Many other Unicode characters are uppercase too.
*
* <p><b>Note:</b> This method cannot handle <a
* href="#supplementary"> supplementary characters</a>. To support
@@ -5496,7 +5496,7 @@
* or it has contributory property Other_Uppercase as defined by the Unicode Standard.
* <p>
* The following are examples of uppercase characters:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
* '\u00C0' '\u00C1' '\u00C2' '\u00C3' '\u00C4' '\u00C5' '\u00C6' '\u00C7'
* '\u00C8' '\u00C9' '\u00CA' '\u00CB' '\u00CC' '\u00CD' '\u00CE' '\u00CF'
@@ -5540,7 +5540,7 @@
* <li>{@code LATIN CAPITAL LETTER N WITH SMALL LETTER J}
* <li>{@code LATIN CAPITAL LETTER D WITH SMALL LETTER Z}
* </ul>
- * <p> Many other Unicode characters are titlecase too.<p>
+ * <p> Many other Unicode characters are titlecase too.
*
* <p><b>Note:</b> This method cannot handle <a
* href="#supplementary"> supplementary characters</a>. To support
diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java
index 500f70d..45c0091 100644
--- a/src/share/classes/java/lang/Class.java
+++ b/src/share/classes/java/lang/Class.java
@@ -91,7 +91,7 @@
* <p> The following example uses a {@code Class} object to print the
* class name of an object:
*
- * <p> <blockquote><pre>
+ * <blockquote><pre>
* void printClassName(Object obj) {
* System.out.println("The class of " + obj +
* " is " + obj.getClass().getName());
@@ -103,7 +103,7 @@
* <cite>The Java™ Language Specification</cite>.
* For example:
*
- * <p> <blockquote>
+ * <blockquote>
* {@code System.out.println("The name of class Foo is: "+Foo.class.getName());}
* </blockquote>
*
@@ -1571,6 +1571,10 @@
* <p> If this {@code Class} object represents a primitive type or void,
* then the returned array has length 0.
*
+ * <p> Static methods declared in superinterfaces of the class or interface
+ * represented by this {@code Class} object are not considered members of
+ * the class or interface.
+ *
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
@@ -1729,6 +1733,10 @@
* <p> If this {@code Class} object represents an array type, then this
* method does not find the {@code clone()} method.
*
+ * <p> Static methods declared in superinterfaces of the class or interface
+ * represented by this {@code Class} object are not considered members of
+ * the class or interface.
+ *
* @param name the name of the method
* @param parameterTypes the list of parameters
* @return the {@code Method} object that matches the specified
@@ -1752,7 +1760,7 @@
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
- Method method = getMethod0(name, parameterTypes);
+ Method method = getMethod0(name, parameterTypes, true);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
@@ -2727,6 +2735,14 @@
}
}
+ void addAllNonStatic(Method[] methods) {
+ for (Method candidate : methods) {
+ if (!Modifier.isStatic(candidate.getModifiers())) {
+ add(candidate);
+ }
+ }
+ }
+
int length() {
return length;
}
@@ -2797,7 +2813,7 @@
MethodArray inheritedMethods = new MethodArray();
Class<?>[] interfaces = getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
- inheritedMethods.addAll(interfaces[i].privateGetPublicMethods());
+ inheritedMethods.addAllNonStatic(interfaces[i].privateGetPublicMethods());
}
if (!isInterface()) {
Class<?> c = getSuperclass();
@@ -2900,7 +2916,7 @@
}
- private Method getMethod0(String name, Class<?>[] parameterTypes) {
+ private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
// Note: the intent is that the search algorithm this routine
// uses be equivalent to the ordering imposed by
// privateGetPublicMethods(). It fetches only the declared
@@ -2913,25 +2929,23 @@
if ((res = searchMethods(privateGetDeclaredMethods(true),
name,
parameterTypes)) != null) {
- return res;
+ if (includeStaticMethods || !Modifier.isStatic(res.getModifiers()))
+ return res;
}
// Search superclass's methods
if (!isInterface()) {
Class<? super T> c = getSuperclass();
if (c != null) {
- if ((res = c.getMethod0(name, parameterTypes)) != null) {
+ if ((res = c.getMethod0(name, parameterTypes, true)) != null) {
return res;
}
}
}
// Search superinterfaces' methods
Class<?>[] interfaces = getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- Class<?> c = interfaces[i];
- if ((res = c.getMethod0(name, parameterTypes)) != null) {
+ for (Class<?> c : interfaces)
+ if ((res = c.getMethod0(name, parameterTypes, false)) != null)
return res;
- }
- }
// Not found
return null;
}
@@ -3300,7 +3314,10 @@
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(annotationData().annotations, annotationClass);
+ AnnotationData annotationData = annotationData();
+ return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations,
+ this,
+ annotationClass);
}
/**
@@ -3330,7 +3347,8 @@
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(annotationData().declaredAnnotations, annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations,
+ annotationClass);
}
/**
@@ -3424,6 +3442,10 @@
return annotationType;
}
+ Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap() {
+ return annotationData().declaredAnnotations;
+ }
+
/* Backing store of user-defined values pertaining to this class.
* Maintained by the ClassValue class.
*/
diff --git a/src/share/classes/java/lang/ClassCastException.java b/src/share/classes/java/lang/ClassCastException.java
index fc9b261..93b6163 100644
--- a/src/share/classes/java/lang/ClassCastException.java
+++ b/src/share/classes/java/lang/ClassCastException.java
@@ -29,7 +29,7 @@
* Thrown to indicate that the code has attempted to cast an object
* to a subclass of which it is not an instance. For example, the
* following code generates a <code>ClassCastException</code>:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* Object x = new Integer(0);
* System.out.println((String)x);
* </pre></blockquote>
diff --git a/src/share/classes/java/lang/ClassLoader.java b/src/share/classes/java/lang/ClassLoader.java
index 7aa5087..875f5ec 100644
--- a/src/share/classes/java/lang/ClassLoader.java
+++ b/src/share/classes/java/lang/ClassLoader.java
@@ -362,7 +362,7 @@
* default implementation of this method searches for classes in the
* following order:
*
- * <p><ol>
+ * <ol>
*
* <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
* has already been loaded. </p></li>
@@ -488,7 +488,7 @@
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(cls)) {
- for (Class intf: cls.getInterfaces()) {
+ for (Class<?> intf: cls.getInterfaces()) {
checkPackageAccess(intf, pd);
}
return;
diff --git a/src/share/classes/java/lang/ClassValue.java b/src/share/classes/java/lang/ClassValue.java
index be190c0..676c2ec 100644
--- a/src/share/classes/java/lang/ClassValue.java
+++ b/src/share/classes/java/lang/ClassValue.java
@@ -692,7 +692,7 @@
/** Remove all stale entries, everywhere. */
private void removeStaleEntries() {
- Entry[] cache = getCache();
+ Entry<?>[] cache = getCache();
removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);
}
diff --git a/src/share/classes/java/lang/Comparable.java b/src/share/classes/java/lang/Comparable.java
index 9d60767..a88cf16 100644
--- a/src/share/classes/java/lang/Comparable.java
+++ b/src/share/classes/java/lang/Comparable.java
@@ -93,7 +93,6 @@
* @see java.util.Comparator
* @since 1.2
*/
-@FunctionalInterface
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
diff --git a/src/share/classes/java/lang/ConditionalSpecialCasing.java b/src/share/classes/java/lang/ConditionalSpecialCasing.java
index 9f3d816..d2ed9d9 100644
--- a/src/share/classes/java/lang/ConditionalSpecialCasing.java
+++ b/src/share/classes/java/lang/ConditionalSpecialCasing.java
@@ -74,7 +74,6 @@
new Entry(0x00CC, new char[]{0x0069, 0x0307, 0x0300}, new char[]{0x00CC}, "lt", 0), // # LATIN CAPITAL LETTER I WITH GRAVE
new Entry(0x00CD, new char[]{0x0069, 0x0307, 0x0301}, new char[]{0x00CD}, "lt", 0), // # LATIN CAPITAL LETTER I WITH ACUTE
new Entry(0x0128, new char[]{0x0069, 0x0307, 0x0303}, new char[]{0x0128}, "lt", 0), // # LATIN CAPITAL LETTER I WITH TILDE
- new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "lt", 0), // # LATIN CAPITAL LETTER I WITH DOT ABOVE
//# ================================================================================
//# Turkish and Azeri
@@ -85,10 +84,7 @@
new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "tr", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I
new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "az", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I
new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "tr", 0), // # LATIN SMALL LETTER I
- new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0), // # LATIN SMALL LETTER I
- //# ================================================================================
- //# Other
- new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "en", 0), // # LATIN CAPITALLETTER I WITH DOT ABOVE
+ new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0) // # LATIN SMALL LETTER I
};
// A hash table that contains the above entries
diff --git a/src/share/classes/java/lang/Double.java b/src/share/classes/java/lang/Double.java
index 1b1aece..690ca6a 100644
--- a/src/share/classes/java/lang/Double.java
+++ b/src/share/classes/java/lang/Double.java
@@ -361,15 +361,11 @@
* <dd><i>SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexFloatingPointLiteral</i>:
* <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexSignificand:</i>
* <dd><i>HexNumeral</i>
@@ -380,15 +376,11 @@
* </i>{@code .} <i>HexDigits</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponent:</i>
* <dd><i>BinaryExponentIndicator SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponentIndicator:</i>
* <dd>{@code p}
diff --git a/src/share/classes/java/lang/Float.java b/src/share/classes/java/lang/Float.java
index e130e92..5cc28f9 100644
--- a/src/share/classes/java/lang/Float.java
+++ b/src/share/classes/java/lang/Float.java
@@ -321,15 +321,11 @@
* <dd><i>SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexFloatingPointLiteral</i>:
* <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>HexSignificand:</i>
* <dd><i>HexNumeral</i>
@@ -340,15 +336,11 @@
* </i>{@code .} <i>HexDigits</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponent:</i>
* <dd><i>BinaryExponentIndicator SignedInteger</i>
* </dl>
*
- * <p>
- *
* <dl>
* <dt><i>BinaryExponentIndicator:</i>
* <dd>{@code p}
diff --git a/src/share/classes/java/lang/Integer.java b/src/share/classes/java/lang/Integer.java
index 7ee4b48..c5d971a 100644
--- a/src/share/classes/java/lang/Integer.java
+++ b/src/share/classes/java/lang/Integer.java
@@ -1123,7 +1123,7 @@
* <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i>
- * <p>
+ *
* <dt><i>Sign:</i>
* <dd>{@code -}
* <dd>{@code +}
diff --git a/src/share/classes/java/lang/Iterable.java b/src/share/classes/java/lang/Iterable.java
index fe9086f..eed3938 100644
--- a/src/share/classes/java/lang/Iterable.java
+++ b/src/share/classes/java/lang/Iterable.java
@@ -42,7 +42,6 @@
* @since 1.5
* @jls 14.14.2 The enhanced for statement
*/
-@FunctionalInterface
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
@@ -52,10 +51,12 @@
Iterator<T> iterator();
/**
- * Performs the given action on the contents of the {@code Iterable}, in the
- * order elements occur when iterating, until all elements have been
- * processed or the action throws an exception. Errors or runtime
- * exceptions thrown by the action are relayed to the caller.
+ * Performs the given action for each element of the {@code Iterable}
+ * until all elements have been processed or the action throws an
+ * exception. Unless otherwise specified by the implementing class,
+ * actions are performed in the order of iteration (if an iteration order
+ * is specified). Exceptions thrown by the action are relayed to the
+ * caller.
*
* @implSpec
* <p>The default implementation behaves as if:
@@ -100,4 +101,3 @@
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
-
diff --git a/src/share/classes/java/lang/Long.java b/src/share/classes/java/lang/Long.java
index bfaf0c4..fa43fa4 100644
--- a/src/share/classes/java/lang/Long.java
+++ b/src/share/classes/java/lang/Long.java
@@ -853,7 +853,7 @@
* <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i>
- * <p>
+ *
* <dt><i>Sign:</i>
* <dd>{@code -}
* <dd>{@code +}
diff --git a/src/share/classes/java/lang/Readable.java b/src/share/classes/java/lang/Readable.java
index e3d08d3..c7a3d1a 100644
--- a/src/share/classes/java/lang/Readable.java
+++ b/src/share/classes/java/lang/Readable.java
@@ -34,7 +34,6 @@
*
* @since 1.5
*/
-@FunctionalInterface
public interface Readable {
/**
diff --git a/src/share/classes/java/lang/RuntimePermission.java b/src/share/classes/java/lang/RuntimePermission.java
index 6dcbc27..9da131b 100644
--- a/src/share/classes/java/lang/RuntimePermission.java
+++ b/src/share/classes/java/lang/RuntimePermission.java
@@ -47,7 +47,6 @@
* The following table lists all the possible RuntimePermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- * <P>
*
* <table border=1 cellpadding=5 summary="permission target name,
* what the target allows,and associated risks">
diff --git a/src/share/classes/java/lang/SecurityManager.java b/src/share/classes/java/lang/SecurityManager.java
index 3565082..635f6db 100644
--- a/src/share/classes/java/lang/SecurityManager.java
+++ b/src/share/classes/java/lang/SecurityManager.java
@@ -56,7 +56,7 @@
* are called by various methods in the Java libraries before those
* methods perform certain potentially sensitive operations. The
* invocation of such a <code>check</code> method typically looks like this:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* SecurityManager security = System.getSecurityManager();
* if (security != null) {
* security.check<i>XXX</i>(argument, . . . );
@@ -323,7 +323,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
* <p>
* This method will return
- * <code>null</code> in the following three cases:<p>
+ * <code>null</code> in the following three cases:
* <ol>
* <li>All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -370,7 +370,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
* <p>
* This method will return
- * <code>null</code> in the following three cases:<p>
+ * <code>null</code> in the following three cases:
* <ol>
* <li>All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -429,7 +429,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
* <p>
* This method will return
- * -1 in the following three cases:<p>
+ * -1 in the following three cases:
* <ol>
* <li>All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -1281,7 +1281,6 @@
* This method calls <code>checkPermission</code> with the
* <code>PropertyPermission(key, "read")</code> permission.
* <p>
- * <p>
* If you override this method, then you should make a call to
* <code>super.checkPropertyAccess</code>
* at the point the overridden method would normally throw an
@@ -1714,7 +1713,7 @@
throw new NullPointerException("class can't be null");
}
if (which != Member.PUBLIC) {
- Class stack[] = getClassContext();
+ Class<?> stack[] = getClassContext();
/*
* stack depth of 4 should be the caller of one of the
* methods in java.lang.Class that invoke checkMember
diff --git a/src/share/classes/java/lang/Short.java b/src/share/classes/java/lang/Short.java
index c764180..9fb3913 100644
--- a/src/share/classes/java/lang/Short.java
+++ b/src/share/classes/java/lang/Short.java
@@ -249,7 +249,7 @@
* <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i>
* <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i>
- * <p>
+ *
* <dt><i>Sign:</i>
* <dd>{@code -}
* <dd>{@code +}
diff --git a/src/share/classes/java/lang/String.java b/src/share/classes/java/lang/String.java
index 2231aa3..9223c0a 100644
--- a/src/share/classes/java/lang/String.java
+++ b/src/share/classes/java/lang/String.java
@@ -47,16 +47,16 @@
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>
* is equivalent to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
* </pre></blockquote><p>
* Here are some more examples of how strings can be used:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* System.out.println("abc");
* String cde = "cde";
* System.out.println("abc" + cde);
@@ -786,7 +786,7 @@
* {@code srcEnd-srcBegin}). The characters are copied into the
* subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* dstbegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
@@ -2598,21 +2598,14 @@
}
if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
- } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT
- lowerChar = Character.ERROR;
} else {
lowerChar = Character.toLowerCase(srcChar);
}
if ((lowerChar == Character.ERROR)
|| (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
if (lowerChar == Character.ERROR) {
- if (!localeDependent && srcChar == '\u0130') {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH);
- } else {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
- }
+ lowerCharArray =
+ ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
} else if (srcCount == 2) {
resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
continue;
@@ -2669,7 +2662,7 @@
* {@code String} may be a different length than the original {@code String}.
* <p>
* Examples of locale-sensitive and 1:M case mappings are in the following table.
- * <p>
+ *
* <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
* <tr>
* <th>Language Code of Locale</th>
diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java
index c5b5e9e..f68a540 100644
--- a/src/share/classes/java/lang/System.java
+++ b/src/share/classes/java/lang/System.java
@@ -26,10 +26,12 @@
import java.io.*;
import java.lang.reflect.Executable;
+import java.lang.annotation.Annotation;
import java.security.AccessControlContext;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
+import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.AllPermission;
@@ -1227,6 +1229,9 @@
public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType();
}
+ public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
+ return klass.getDeclaredAnnotationMap();
+ }
public byte[] getRawClassAnnotations(Class<?> klass) {
return klass.getRawAnnotations();
}
diff --git a/src/share/classes/java/lang/Thread.java b/src/share/classes/java/lang/Thread.java
index c2f5561..13d8ac2 100644
--- a/src/share/classes/java/lang/Thread.java
+++ b/src/share/classes/java/lang/Thread.java
@@ -76,7 +76,7 @@
* <code>Thread</code>. An instance of the subclass can then be
* allocated and started. For example, a thread that computes primes
* larger than a stated value could be written as follows:
- * <p><hr><blockquote><pre>
+ * <hr><blockquote><pre>
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
@@ -91,7 +91,7 @@
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* PrimeThread p = new PrimeThread(143);
* p.start();
* </pre></blockquote>
@@ -102,7 +102,7 @@
* then be allocated, passed as an argument when creating
* <code>Thread</code>, and started. The same example in this other
* style looks like the following:
- * <p><hr><blockquote><pre>
+ * <hr><blockquote><pre>
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
@@ -117,7 +117,7 @@
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
diff --git a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
index 793a2d1..e1c82d8 100644
--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
@@ -101,7 +101,6 @@
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
- * @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
*/
@@ -114,7 +113,7 @@
boolean isSerializable,
Class<?>[] markerInterfaces,
MethodType[] additionalBridges)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
this.targetClass = caller.lookupClass();
this.invokedType = invokedType;
@@ -160,7 +159,7 @@
* @throws ReflectiveOperationException
*/
abstract CallSite buildCallSite()
- throws ReflectiveOperationException, LambdaConversionException;
+ throws LambdaConversionException;
/**
* Check the meta-factory arguments for errors
diff --git a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
index 4866807..a85c505 100644
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
+++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
@@ -26,16 +26,19 @@
package java.lang.invoke;
import jdk.internal.org.objectweb.asm.*;
+import sun.invoke.util.BytecodeDescriptor;
import sun.misc.Unsafe;
import sun.security.action.GetPropertyAction;
import java.io.FilePermission;
+import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
+import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.PropertyPermission;
+import java.util.Set;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
@@ -50,14 +53,19 @@
private static final int CLASSFILE_VERSION = 51;
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
- private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
+ private static final String JAVA_LANG_OBJECT = "java/lang/Object";
private static final String NAME_CTOR = "<init>";
+ private static final String NAME_FACTORY = "get$Lambda";
//Serialization support
private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
+ private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
+ private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
+ private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
- private static final String NAME_OBJECT = "java/lang/Object";
+ private static final String NAME_METHOD_READ_OBJECT = "readObject";
+ private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
private static final String DESCR_CTOR_SERIALIZED_LAMBDA
= MethodType.methodType(void.class,
Class.class,
@@ -65,6 +73,12 @@
int.class, String.class, String.class, String.class,
String.class,
Object[].class).toMethodDescriptorString();
+ private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
+ = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
+ private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
+
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
// Used to ensure that each spun class name is unique
private static final AtomicInteger counter = new AtomicInteger(0);
@@ -84,15 +98,12 @@
private final String implMethodClassName; // Name of type containing implementation "CC"
private final String implMethodName; // Name of implementation method "impl"
private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;"
- private final Type[] implMethodArgumentTypes; // ASM types for implementation method parameters
- private final Type implMethodReturnType; // ASM type for implementation method return type "Ljava/lang/String;"
+ private final Class<?> implMethodReturnClass; // class for implementaion method return type "Ljava/lang/String;"
private final MethodType constructorType; // Generated class constructor type "(CC)void"
- private final String constructorDesc; // Type descriptor for constructor "(LCC;)V"
private final ClassWriter cw; // ASM class writer
- private final Type[] argTypes; // ASM types for the constructor arguments
private final String[] argNames; // Generated names for the constructor arguments
+ private final String[] argDescs; // Type descriptors for the constructor arguments
private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1"
- private final Type[] instantiatedArgumentTypes; // ASM types for the functional interface arguments
/**
* General meta-factory constructor, supporting both standard cases and
@@ -128,7 +139,6 @@
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
- * @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
*/
@@ -141,29 +151,30 @@
boolean isSerializable,
Class<?>[] markerInterfaces,
MethodType[] additionalBridges)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
super(caller, invokedType, samMethodName, samMethodType,
implMethod, instantiatedMethodType,
isSerializable, markerInterfaces, additionalBridges);
implMethodClassName = implDefiningClass.getName().replace('.', '/');
implMethodName = implInfo.getName();
implMethodDesc = implMethodType.toMethodDescriptorString();
- Type implMethodAsmType = Type.getMethodType(implMethodDesc);
- implMethodArgumentTypes = implMethodAsmType.getArgumentTypes();
- implMethodReturnType = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
- ? Type.getObjectType(implMethodClassName)
- : implMethodAsmType.getReturnType();
+ implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
+ ? implDefiningClass
+ : implMethodType.returnType();
constructorType = invokedType.changeReturnType(Void.TYPE);
- constructorDesc = constructorType.toMethodDescriptorString();
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- argTypes = Type.getArgumentTypes(constructorDesc);
- argNames = new String[argTypes.length];
- for (int i = 0; i < argTypes.length; i++) {
- argNames[i] = "arg$" + (i + 1);
+ int parameterCount = invokedType.parameterCount();
+ if (parameterCount > 0) {
+ argNames = new String[parameterCount];
+ argDescs = new String[parameterCount];
+ for (int i = 0; i < parameterCount; i++) {
+ argNames[i] = "arg$" + (i + 1);
+ argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
+ }
+ } else {
+ argNames = argDescs = EMPTY_STRING_ARRAY;
}
- instantiatedArgumentTypes = Type.getArgumentTypes(
- instantiatedMethodType.toMethodDescriptorString());
}
/**
@@ -179,36 +190,44 @@
* is not found
*/
@Override
- CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
+ CallSite buildCallSite() throws LambdaConversionException {
final Class<?> innerClass = spinInnerClass();
if (invokedType.parameterCount() == 0) {
final Constructor[] ctrs = AccessController.doPrivileged(
new PrivilegedAction<Constructor[]>() {
@Override
public Constructor[] run() {
- return innerClass.getDeclaredConstructors();
+ Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
+ if (ctrs.length == 1) {
+ // The lambda implementing inner class constructor is private, set
+ // it accessible (by us) before creating the constant sole instance
+ ctrs[0].setAccessible(true);
+ }
+ return ctrs;
}
- });
+ });
if (ctrs.length != 1) {
- throw new ReflectiveOperationException("Expected one lambda constructor for "
+ throw new LambdaConversionException("Expected one lambda constructor for "
+ innerClass.getCanonicalName() + ", got " + ctrs.length);
}
- // The lambda implementing inner class constructor is private, set
- // it accessible (by us) before creating the constant sole instance
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- ctrs[0].setAccessible(true);
- return null;
- }
- });
- Object inst = ctrs[0].newInstance();
- return new ConstantCallSite(MethodHandles.constant(samBase, inst));
+
+ try {
+ Object inst = ctrs[0].newInstance();
+ return new ConstantCallSite(MethodHandles.constant(samBase, inst));
+ }
+ catch (ReflectiveOperationException e) {
+ throw new LambdaConversionException("Exception instantiating lambda object", e);
+ }
} else {
- return new ConstantCallSite(
- MethodHandles.Lookup.IMPL_LOOKUP
- .findConstructor(innerClass, constructorType)
- .asType(constructorType.changeReturnType(samBase)));
+ try {
+ UNSAFE.ensureClassInitialized(innerClass);
+ return new ConstantCallSite(
+ MethodHandles.Lookup.IMPL_LOOKUP
+ .findStatic(innerClass, NAME_FACTORY, invokedType));
+ }
+ catch (ReflectiveOperationException e) {
+ throw new LambdaConversionException("Exception finding constructor", e);
+ }
}
}
@@ -228,44 +247,59 @@
* is not found
*/
private Class<?> spinInnerClass() throws LambdaConversionException {
- String[] interfaces = new String[markerInterfaces.length + 1];
- interfaces[0] = samBase.getName().replace('.', '/');
- for (int i=0; i<markerInterfaces.length; i++) {
- interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
+ String[] interfaces;
+ String samIntf = samBase.getName().replace('.', '/');
+ boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
+ if (markerInterfaces.length == 0) {
+ interfaces = new String[]{samIntf};
+ } else {
+ // Assure no duplicate interfaces (ClassFormatError)
+ Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
+ itfs.add(samIntf);
+ for (Class<?> markerInterface : markerInterfaces) {
+ itfs.add(markerInterface.getName().replace('.', '/'));
+ accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
+ }
+ interfaces = itfs.toArray(new String[itfs.size()]);
}
+
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null,
- NAME_MAGIC_ACCESSOR_IMPL, interfaces);
+ JAVA_LANG_OBJECT, interfaces);
// Generate final fields to be filled in by constructor
- for (int i = 0; i < argTypes.length; i++) {
+ for (int i = 0; i < argDescs.length; i++) {
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
argNames[i],
- argTypes[i].getDescriptor(),
+ argDescs[i],
null, null);
fv.visitEnd();
}
generateConstructor();
+ if (invokedType.parameterCount() != 0) {
+ generateFactory();
+ }
+
// Forward the SAM method
- String methodDescriptor = samMethodType.toMethodDescriptorString();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
- methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ samMethodType.toMethodDescriptorString(), null, null);
+ new ForwardingMethodGenerator(mv).generate(samMethodType);
// Forward the bridges
if (additionalBridges != null) {
for (MethodType mt : additionalBridges) {
- methodDescriptor = mt.toMethodDescriptorString();
mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
- methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ mt.toMethodDescriptorString(), null, null);
+ new ForwardingMethodGenerator(mv).generate(mt);
}
}
if (isSerializable)
- generateWriteReplace();
+ generateSerializationFriendlyMethods();
+ else if (accidentallySerializable)
+ generateSerializationHostileMethods();
cw.visitEnd();
@@ -287,21 +321,27 @@
new PropertyPermission("user.dir", "read"));
}
- ClassLoader loader = targetClass.getClassLoader();
- ProtectionDomain pd = (loader == null)
- ? null
- : AccessController.doPrivileged(
- new PrivilegedAction<ProtectionDomain>() {
- @Override
- public ProtectionDomain run() {
- return targetClass.getProtectionDomain();
- }
- }
- );
+ return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
+ }
- return UNSAFE.defineClass(lambdaClassName,
- classBytes, 0, classBytes.length,
- loader, pd);
+ /**
+ * Generate the factory method for the class
+ */
+ private void generateFactory() {
+ MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
+ m.visitCode();
+ m.visitTypeInsn(NEW, lambdaClassName);
+ m.visitInsn(Opcodes.DUP);
+ int parameterCount = invokedType.parameterCount();
+ for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
+ Class<?> argType = invokedType.parameterType(typeIndex);
+ m.visitVarInsn(getLoadOpcode(argType), varIndex);
+ varIndex += getParameterSize(argType);
+ }
+ m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString());
+ m.visitInsn(ARETURN);
+ m.visitMaxs(-1, -1);
+ m.visitEnd();
}
/**
@@ -310,18 +350,18 @@
private void generateConstructor() {
// Generate constructor
MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
- constructorDesc, null, null);
+ constructorType.toMethodDescriptorString(), null, null);
ctor.visitCode();
ctor.visitVarInsn(ALOAD, 0);
- ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR,
+ ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
METHOD_DESCRIPTOR_VOID);
- int lvIndex = 0;
- for (int i = 0; i < argTypes.length; i++) {
+ int parameterCount = invokedType.parameterCount();
+ for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
ctor.visitVarInsn(ALOAD, 0);
- ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1);
- lvIndex += argTypes[i].getSize();
- ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
+ Class<?> argType = invokedType.parameterType(i);
+ ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
+ lvIndex += getParameterSize(argType);
+ ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
}
ctor.visitInsn(RETURN);
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
@@ -330,9 +370,9 @@
}
/**
- * Generate the writeReplace method (if needed for serialization)
+ * Generate a writeReplace method that supports serialization
*/
- private void generateWriteReplace() {
+ private void generateSerializationFriendlyMethods() {
TypeConvertingMethodAdapter mv
= new TypeConvertingMethodAdapter(
cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
@@ -351,16 +391,14 @@
mv.visitLdcInsn(implInfo.getName());
mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
-
- mv.iconst(argTypes.length);
- mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT);
- for (int i = 0; i < argTypes.length; i++) {
+ mv.iconst(argDescs.length);
+ mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
+ for (int i = 0; i < argDescs.length; i++) {
mv.visitInsn(DUP);
mv.iconst(i);
mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
- mv.boxIfTypePrimitive(argTypes[i]);
+ mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
+ mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
mv.visitInsn(AASTORE);
}
mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
@@ -372,6 +410,37 @@
}
/**
+ * Generate a readObject/writeObject method that is hostile to serialization
+ */
+ private void generateSerializationHostileMethods() {
+ MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
+ NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
+ null, SER_HOSTILE_EXCEPTIONS);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Non-serializable lambda");
+ mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
+ DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(ATHROW);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+
+ mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
+ NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
+ null, SER_HOSTILE_EXCEPTIONS);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Non-serializable lambda");
+ mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
+ DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(ATHROW);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ /**
* This class generates a method body which calls the lambda implementation
* method, converting arguments, as needed.
*/
@@ -381,20 +450,19 @@
super(mv);
}
- void generate(String methodDescriptor) {
+ void generate(MethodType methodType) {
visitCode();
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
visitTypeInsn(NEW, implMethodClassName);
visitInsn(DUP);
}
- for (int i = 0; i < argTypes.length; i++) {
+ for (int i = 0; i < argNames.length; i++) {
visitVarInsn(ALOAD, 0);
- visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
+ visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
}
- convertArgumentTypes(Type.getArgumentTypes(methodDescriptor));
+ convertArgumentTypes(methodType);
// Invoke the method we want to forward to
visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc);
@@ -402,46 +470,36 @@
// Convert the return value (if any) and return it
// Note: if adapting from non-void to void, the 'return'
// instruction will pop the unneeded result
- Type samReturnType = Type.getReturnType(methodDescriptor);
- convertType(implMethodReturnType, samReturnType, samReturnType);
- visitInsn(samReturnType.getOpcode(Opcodes.IRETURN));
+ Class<?> samReturnClass = methodType.returnType();
+ convertType(implMethodReturnClass, samReturnClass, samReturnClass);
+ visitInsn(getReturnOpcode(samReturnClass));
// Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
visitMaxs(-1, -1);
visitEnd();
}
- private void convertArgumentTypes(Type[] samArgumentTypes) {
+ private void convertArgumentTypes(MethodType samType) {
int lvIndex = 0;
boolean samIncludesReceiver = implIsInstanceMethod &&
- argTypes.length == 0;
+ invokedType.parameterCount() == 0;
int samReceiverLength = samIncludesReceiver ? 1 : 0;
if (samIncludesReceiver) {
// push receiver
- Type rcvrType = samArgumentTypes[0];
- Type instantiatedRcvrType = instantiatedArgumentTypes[0];
-
- visitVarInsn(rcvrType.getOpcode(ILOAD), lvIndex + 1);
- lvIndex += rcvrType.getSize();
- convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType);
+ Class<?> rcvrType = samType.parameterType(0);
+ visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
+ lvIndex += getParameterSize(rcvrType);
+ convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
}
- int argOffset = implMethodArgumentTypes.length - samArgumentTypes.length;
- for (int i = samReceiverLength; i < samArgumentTypes.length; i++) {
- Type argType = samArgumentTypes[i];
- Type targetType = implMethodArgumentTypes[argOffset + i];
- Type instantiatedArgType = instantiatedArgumentTypes[i];
-
- visitVarInsn(argType.getOpcode(ILOAD), lvIndex + 1);
- lvIndex += argType.getSize();
- convertType(argType, targetType, instantiatedArgType);
+ int samParametersLength = samType.parameterCount();
+ int argOffset = implMethodType.parameterCount() - samParametersLength;
+ for (int i = samReceiverLength; i < samParametersLength; i++) {
+ Class<?> argType = samType.parameterType(i);
+ visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
+ lvIndex += getParameterSize(argType);
+ convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
}
}
- private void convertType(Type argType, Type targetType, Type functionalType) {
- convertType(argType.getDescriptor(),
- targetType.getDescriptor(),
- functionalType.getDescriptor());
- }
-
private int invocationOpcode() throws InternalError {
switch (implKind) {
case MethodHandleInfo.REF_invokeStatic:
@@ -459,4 +517,43 @@
}
}
}
+
+ static int getParameterSize(Class<?> c) {
+ if (c == Void.TYPE) {
+ return 0;
+ } else if (c == Long.TYPE || c == Double.TYPE) {
+ return 2;
+ }
+ return 1;
+ }
+
+ static int getLoadOpcode(Class<?> c) {
+ if(c == Void.TYPE) {
+ throw new InternalError("Unexpected void type of load opcode");
+ }
+ return ILOAD + getOpcodeOffset(c);
+ }
+
+ static int getReturnOpcode(Class<?> c) {
+ if(c == Void.TYPE) {
+ return RETURN;
+ }
+ return IRETURN + getOpcodeOffset(c);
+ }
+
+ private static int getOpcodeOffset(Class<?> c) {
+ if (c.isPrimitive()) {
+ if (c == Long.TYPE) {
+ return 1;
+ } else if (c == Float.TYPE) {
+ return 2;
+ } else if (c == Double.TYPE) {
+ return 3;
+ }
+ return 0;
+ } else {
+ return 4;
+ }
+ }
+
}
diff --git a/src/share/classes/java/lang/invoke/LambdaMetafactory.java b/src/share/classes/java/lang/invoke/LambdaMetafactory.java
index 87c7923..5bea020 100644
--- a/src/share/classes/java/lang/invoke/LambdaMetafactory.java
+++ b/src/share/classes/java/lang/invoke/LambdaMetafactory.java
@@ -29,88 +29,128 @@
import java.util.Arrays;
/**
- * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
+ * <p>Methods to facilitate the creation of simple "function objects" that
+ * implement one or more interfaces by delegation to a provided {@link MethodHandle},
+ * possibly after type adaptation and partial evaluation of arguments. These
+ * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
+ * call sites, to support the <em>lambda expression</em> and <em>method
+ * reference expression</em> features of the Java Programming Language.
*
- * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
- * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for
- * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole
- * method of the functional interface and the implementation method, and returns an object (the lambda object) that
- * implements the target type. Methods of the lambda object invoke the implementation method. For method
- * references, the implementation method is simply the referenced method; for lambda expressions, the
- * implementation method is produced by the compiler based on the body of the lambda expression. The methods in
- * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the
- * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories.
- *
- * <p>The bootstrap methods in this class take the information about the functional interface, the implementation
- * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
- * produces the lambda object.
- *
- * <p>When parameterized types are used, the instantiated type of the functional interface method may be different
- * from that in the functional interface. For example, consider
- * {@code interface I<T> { int m(T x); }} if this functional interface type is used in a lambda
- * {@code I<Byte>; v = ...}, we need both the actual functional interface method which has the signature
- * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply
- * <I>instantiated method type</I>), which has signature
- * {@code (Byte)int}.
- *
- * <p>The argument list of the implementation method and the argument list of the functional interface method(s)
- * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments
- * captured by the lambda expression; there may also be differences resulting from permitted adaptations of
- * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args,
- * but this is expected to be handled by the compiler.
- *
- * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list. The
- * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at
- * invocation time. The bootstrap method has access to the entire static argument list (which in this case,
- * contains method handles describing the implementation method and the canonical functional interface method),
- * as well as a method signature describing the number and static types (but not the values) of the dynamic
- * arguments, and the static return type of the invokedynamic site.
- *
- * <p>The implementation method is described with a method handle. In theory, any method handle could be used.
- * Currently supported are method handles representing invocation of virtual, interface, constructor and static
- * methods.
- *
- * <p>Assume:
+ * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
+ * proceeds in order through three phases:
* <ul>
- * <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li>
- * <li>then the instantiated method type also has N arguments, of types (T1, T2, ... Tn) and return type Rt</li>
- * <li>the implementation method has M arguments, of types (A1..Am) and return type Ra,</li>
- * <li>the dynamic argument list has K arguments of types (D1..Dk), and the invokedynamic return site has
- * type Rd</li>
- * <li>the functional interface type is F</li>
+ * <li><em>Linkage</em> occurs when the methods in this class are invoked.
+ * They take as arguments an interface to be implemented (typically a
+ * <em>functional interface</em>, one with a single abstract method), a
+ * name and signature of a method from that interface to be implemented, a
+ * method handle describing the desired implementation behavior
+ * for that method, and possibly other additional metadata, and produce a
+ * {@link CallSite} whose target can be used to create suitable function
+ * objects. Linkage may involve dynamically loading a new class that
+ * implements the target interface. The {@code CallSite} can be considered a
+ * "factory" for function objects and so these linkage methods are referred
+ * to as "metafactories".</li>
+ *
+ * <li><em>Capture</em> occurs when the {@code CallSite}'s target is
+ * invoked, typically through an {@code invokedynamic} call site,
+ * producing a function object. This may occur many times for
+ * a single factory {@code CallSite}. Capture may involve allocation of a
+ * new function object, or may return an existing function object. The
+ * behavior {@code MethodHandle} may have additional parameters beyond those
+ * of the specified interface method; these are referred to as <em>captured
+ * parameters</em>, which must be provided as arguments to the
+ * {@code CallSite} target, and which may be early-bound to the behavior
+ * {@code MethodHandle}. The number of captured parameters and their types
+ * are determined during linkage.</li>
+ *
+ * <li><em>Invocation</em> occurs when an implemented interface method
+ * is invoked on a function object. This may occur many times for a single
+ * function object. The method referenced by the behavior {@code MethodHandle}
+ * is invoked with the captured arguments and any additional arguments
+ * provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
* </ul>
*
- * <p>The following signature invariants must hold:
+ * <p>It is sometimes useful to restrict the set of inputs or results permitted
+ * at invocation. For example, when the generic interface {@code Predicate<T>}
+ * is parameterized as {@code Predicate<String>}, the input must be a
+ * {@code String}, even though the method to implement allows any {@code Object}.
+ * At linkage time, an additional {@link MethodType} parameter describes the
+ * "instantiated" method type; on invocation, the arguments and eventual result
+ * are checked against this {@code MethodType}.
+ *
+ * <p>This class provides two forms of linkage methods: a standard version
+ * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
+ * using an optimized protocol, and an alternate version
+ * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}).
+ * The alternate version is a generalization of the standard version, providing
+ * additional control over the behavior of the generated function objects via
+ * flags and additional arguments. The alternate version adds the ability to
+ * manage the following attributes of function objects:
+ *
* <ul>
- * <li>Rd is a subtype of F</li>
- * <li>For i=1..N, Ti is a subtype of Ui</li>
- * <li>Either Rt and Ru are primitive and are the same type, or both are reference types and
- * Rt is a subtype of Ru</li>
- * <li>If the implementation method is a static method:
- * <ul>
- * <li>K + N = M</li>
- * <li>For i=1..K, Di = Ai</li>
- * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
- * </ul></li>
- * <li>If the implementation method is an instance method:
- * <ul>
- * <li>K + N = M + 1</li>
- * <li>D1 must be a subtype of the enclosing class for the implementation method</li>
- * <li>For i=2..K, Di = Aj, where j=i-1</li>
- * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
- * </ul></li>
- * <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
+ * <li><em>Bridging.</em> It is sometimes useful to implement multiple
+ * variations of the method signature, involving argument or return type
+ * adaptation. This occurs when multiple distinct VM signatures for a method
+ * are logically considered to be the same method by the language. The
+ * flag {@code FLAG_BRIDGES} indicates that a list of additional
+ * {@code MethodType}s will be provided, each of which will be implemented
+ * by the resulting function object. These methods will share the same
+ * name and instantiated type.</li>
+ *
+ * <li><em>Multiple interfaces.</em> If needed, more than one interface
+ * can be implemented by the function object. (These additional interfaces
+ * are typically marker interfaces with no methods.) The flag {@code FLAG_MARKERS}
+ * indicates that a list of additional interfaces will be provided, each of
+ * which should be implemented by the resulting function object.</li>
+ *
+ * <li><em>Serializability.</em> The generated function objects do not
+ * generally support serialization. If desired, {@code FLAG_SERIALIZABLE}
+ * can be used to indicate that the function objects should be serializable.
+ * Serializable function objects will use, as their serialized form,
+ * instances of the class {@code SerializedLambda}, which requires additional
+ * assistance from the capturing class (the class described by the
+ * {@link MethodHandles.Lookup} parameter {@code caller}); see
+ * {@link SerializedLambda} for details.</li>
* </ul>
*
- * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
- * the completely known instantiated return type is adapted to the implementation arguments. Because the
- * instantiated type of the implementation method is not available, the adaptability of return types cannot be
- * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
- * done on return type, while a strict version is applied to arguments.
+ * <p>Assume the linkage arguments are as follows:
+ * <ul>
+ * <li>{@code invokedType} (describing the {@code CallSite} signature) has
+ * K parameters of types (D1..Dk) and return type Rd;</li>
+ * <li>{@code samMethodType} (describing the implemented method type) has N
+ * parameters, of types (U1..Un) and return type Ru;</li>
+ * <li>{@code implMethod} (the {@code MethodHandle} providing the
+ * implementation has M parameters, of types (A1..Am) and return type Ra
+ * (if the method describes an instance method, the method type of this
+ * method handle already includes an extra first argument corresponding to
+ * the receiver);</li>
+ * <li>{@code instantiatedMethodType} (allowing restrictions on invocation)
+ * has N parameters, of types (T1..Tn) and return type Rt.</li>
+ * </ul>
+ *
+ * <p>Then the following linkage invariants must hold:
+ * <ul>
+ * <li>Rd is an interface</li>
+ * <li>{@code implMethod} is a <em>direct method handle</em></li>
+ * <li>{@code samMethodType} and {@code instantiatedMethodType} have the same
+ * arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
+ * both reference types and Ti is a subtype of Ui</li>
+ * <li>Either Rt and Ru are the same type, or both are reference types and
+ * Rt is a subtype of Ru</li>
+ * <li>K + N = M</li>
+ * <li>For i=1..K, Di = Ai</li>
+ * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
+ * <li>The return type Rt is void, or the return type Ra is not void and is
+ * adaptable to Rt</li>
+ * </ul>
+ *
+ * <p>Further, at capture time, if {@code implMethod} corresponds to an instance
+ * method, and there are any capture arguments ({@code K > 0}), then the first
+ * capture argument (corresponding to the receiver) must be non-null.
*
* <p>A type Q is considered adaptable to S as follows:
* <table summary="adaptable types">
- * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
+ * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Invocation-time checks</th></tr>
* <tr>
* <td>Primitive</td><td>Primitive</td>
* <td>Q can be converted to S via a primitive widening conversion</td>
@@ -123,27 +163,59 @@
* </tr>
* <tr>
* <td>Reference</td><td>Primitive</td>
- * <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
- * <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
- * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
+ * <td>for parameter types: Q is a primitive wrapper and Primitive(Q)
+ * can be widened to S
+ * <br>for return types: If Q is a primitive wrapper, check that
+ * Primitive(Q) can be widened to S</td>
+ * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
+ * for example Number for numeric types</td>
* </tr>
* <tr>
* <td>Reference</td><td>Reference</td>
- * <td>strict: S is a supertype of Q
- * <br>loose: none</td>
+ * <td>for parameter types: S is a supertype of Q
+ * <br>for return types: none</td>
* <td>Cast from Q to S</td>
* </tr>
* </table>
*
- * The default bootstrap ({@link #metafactory}) represents the common cases and uses an optimized protocol.
- * Alternate bootstraps (e.g., {@link #altMetafactory}) exist to support uncommon cases such as serialization
- * or additional marker superinterfaces.
+ * @apiNote These linkage methods are designed to support the evaluation
+ * of <em>lambda expressions</em> and <em>method references</em> in the Java
+ * Language. For every lambda expressions or method reference in the source code,
+ * there is a target type which is a functional interface. Evaluating a lambda
+ * expression produces an object of its target type. The recommended mechanism
+ * for evaluating lambda expressions is to desugar the lambda body to a method,
+ * invoke an invokedynamic call site whose static argument list describes the
+ * sole method of the functional interface and the desugared implementation
+ * method, and returns an object (the lambda object) that implements the target
+ * type. (For method references, the implementation method is simply the
+ * referenced method; no desugaring is needed.)
*
+ * <p>The argument list of the implementation method and the argument list of
+ * the interface method(s) may differ in several ways. The implementation
+ * methods may have additional arguments to accommodate arguments captured by
+ * the lambda expression; there may also be differences resulting from permitted
+ * adaptations of arguments, such as casting, boxing, unboxing, and primitive
+ * widening. (Varargs adaptations are not handled by the metafactories; these are
+ * expected to be handled by the caller.)
+ *
+ * <p>Invokedynamic call sites have two argument lists: a static argument list
+ * and a dynamic argument list. The static argument list is stored in the
+ * constant pool; the dynamic argument is pushed on the operand stack at capture
+ * time. The bootstrap method has access to the entire static argument list
+ * (which in this case, includes information describing the implementation method,
+ * the target interface, and the target interface method(s)), as well as a
+ * method signature describing the number and static types (but not the values)
+ * of the dynamic arguments and the static return type of the invokedynamic site.
+ *
+ * @implNote The implementation method is described with a method handle. In
+ * theory, any method handle could be used. Currently supported are direct method
+ * handles representing invocation of virtual, interface, constructor and static
+ * methods.
*/
public class LambdaMetafactory {
- /** Flag for alternate metafactories indicating the lambda object is
- * must to be serializable */
+ /** Flag for alternate metafactories indicating the lambda object
+ * must be serializable */
public static final int FLAG_SERIALIZABLE = 1 << 0;
/**
@@ -163,41 +235,58 @@
private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
/**
- * Standard meta-factory for conversion of lambda expressions or method
- * references to functional interfaces.
+ * Facilitates the creation of simple "function objects" that implement one
+ * or more interfaces by delegation to a provided {@link MethodHandle},
+ * after appropriate type adaptation and partial evaluation of arguments.
+ * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
+ * call sites, to support the <em>lambda expression</em> and <em>method
+ * reference expression</em> features of the Java Programming Language.
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @param invokedName Stacked automatically by VM; the name of the invoked
- * method as it appears at the call site.
- * Used as the name of the functional interface method
- * to which the lambda or method reference is being
- * converted.
- * @param invokedType Stacked automatically by VM; the signature of the
- * invoked method, which includes the expected static
- * type of the returned lambda object, and the static
- * types of the captured arguments for the lambda.
+ * <p>This is the standard, streamlined metafactory; additional flexibility
+ * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
+ * A general description of the behavior of this method is provided
+ * {@link LambdaMetafactory above}.
+ *
+ * <p>When the target of the {@code CallSite} returned from this method is
+ * invoked, the resulting function objects are instances of a class which
+ * implements the interface named by the return type of {@code invokedType},
+ * declares a method with the name given by {@code invokedName} and the
+ * signature given by {@code samMethodType}. It may also override additional
+ * methods from {@code Object}.
+ *
+ * @param caller Represents a lookup context with the accessibility
+ * privileges of the caller. When used with {@code invokedynamic},
+ * this is stacked automatically by the VM.
+ * @param invokedName The name of the method to implement. When used with
+ * {@code invokedynamic}, this is provided by the
+ * {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
+ * @param invokedType The expected signature of the {@code CallSite}. The
+ * parameter types represent the types of capture variables;
+ * the return type is the interface to implement. When
+ * used with {@code invokedynamic}, this is provided by
+ * the {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
* In the event that the implementation method is an
- * instance method, the first argument in the invocation
- * signature will correspond to the receiver.
- * @param samMethodType MethodType of the method in the functional interface
- * to which the lambda or method reference is being
- * converted, represented as a MethodType.
- * @param implMethod The implementation method which should be called
- * (with suitable adaptation of argument types, return
- * types, and adjustment for captured arguments) when
- * methods of the resulting functional interface instance
- * are invoked.
- * @param instantiatedMethodType The signature of the primary functional
- * interface method after type variables
- * are substituted with their instantiation
- * from the capture site
- * @return a CallSite, which, when invoked, will return an instance of the
- * functional interface
- * @throws ReflectiveOperationException if the caller is not able to
- * reconstruct one of the method handles
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * instance method and this signature has any parameters,
+ * the first parameter in the invocation signature must
+ * correspond to the receiver.
+ * @param samMethodType Signature and return type of method to be implemented
+ * by the function object.
+ * @param implMethod A direct method handle describing the implementation
+ * method which should be called (with suitable adaptation
+ * of argument types, return types, and with captured
+ * arguments prepended to the invocation arguments) at
+ * invocation time.
+ * @param instantiatedMethodType The signature and return type that should
+ * be enforced dynamically at invocation time.
+ * This may be the same as {@code samMethodType},
+ * or may be a specialization of it.
+ * @return a CallSite whose target can be used to perform capture, generating
+ * instances of the interface named by {@code invokedType}
+ * @throws LambdaConversionException If any of the linkage invariants
+ * described {@link LambdaMetafactory above}
+ * are violated
*/
public static CallSite metafactory(MethodHandles.Lookup caller,
String invokedName,
@@ -205,7 +294,7 @@
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
AbstractValidatingLambdaMetafactory mf;
mf = new InnerClassLambdaMetafactory(caller, invokedType,
invokedName, samMethodType,
@@ -216,60 +305,128 @@
}
/**
- * Alternate meta-factory for conversion of lambda expressions or method
- * references to functional interfaces, which supports serialization and
- * other uncommon options.
+ * Facilitates the creation of simple "function objects" that implement one
+ * or more interfaces by delegation to a provided {@link MethodHandle},
+ * after appropriate type adaptation and partial evaluation of arguments.
+ * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
+ * call sites, to support the <em>lambda expression</em> and <em>method
+ * reference expression</em> features of the Java Programming Language.
*
- * The declared argument list for this method is:
+ * <p>This is the general, more flexible metafactory; a streamlined version
+ * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
+ * A general description of the behavior of this method is provided
+ * {@link LambdaMetafactory above}.
*
+ * <p>The argument list for this method includes three fixed parameters,
+ * corresponding to the parameters automatically stacked by the VM for the
+ * bootstrap method in an {@code invokedynamic} invocation, and an {@code Object[]}
+ * parameter that contains additional parameters. The declared argument
+ * list for this method is:
+ *
+ * <pre>{@code
* CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName,
* MethodType invokedType,
* Object... args)
+ * }</pre>
*
- * but it behaves as if the argument list is:
+ * <p>but it behaves as if the argument list is as follows:
*
+ * <pre>{@code
* CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName,
* MethodType invokedType,
- * MethodType samMethodType
+ * MethodType samMethodType,
* MethodHandle implMethod,
* MethodType instantiatedMethodType,
* int flags,
- * int markerInterfaceCount, // IF flags has MARKERS set
- * Class... markerInterfaces // IF flags has MARKERS set
- * int bridgeCount, // IF flags has BRIDGES set
- * MethodType... bridges // IF flags has BRIDGES set
+ * int markerInterfaceCount, // IF flags has MARKERS set
+ * Class... markerInterfaces, // IF flags has MARKERS set
+ * int bridgeCount, // IF flags has BRIDGES set
+ * MethodType... bridges // IF flags has BRIDGES set
* )
+ * }</pre>
*
+ * <p>Arguments that appear in the argument list for
+ * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
+ * have the same specification as in that method. The additional arguments
+ * are interpreted as follows:
+ * <ul>
+ * <li>{@code flags} indicates additional options; this is a bitwise
+ * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
+ * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
+ * <li>{@code markerInterfaceCount} is the number of additional interfaces
+ * the function object should implement, and is present if and only if the
+ * {@code FLAG_MARKERS} flag is set.</li>
+ * <li>{@code markerInterfaces} is a variable-length list of additional
+ * interfaces to implement, whose length equals {@code markerInterfaceCount},
+ * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
+ * <li>{@code bridgeCount} is the number of additional method signatures
+ * the function object should implement, and is present if and only if
+ * the {@code FLAG_BRIDGES} flag is set.</li>
+ * <li>{@code bridges} is a variable-length list of additional
+ * methods signatures to implement, whose length equals {@code bridgeCount},
+ * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
+ * </ul>
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @param invokedName Stacked automatically by VM; the name of the invoked
- * method as it appears at the call site.
- * Used as the name of the functional interface method
- * to which the lambda or method reference is being
- * converted.
- * @param invokedType Stacked automatically by VM; the signature of the
- * invoked method, which includes the expected static
- * type of the returned lambda object, and the static
- * types of the captured arguments for the lambda.
+ * <p>Each class named by {@code markerInterfaces} is subject to the same
+ * restrictions as {@code Rd}, the return type of {@code invokedType},
+ * as described {@link LambdaMetafactory above}. Each {@code MethodType}
+ * named by {@code bridges} is subject to the same restrictions as
+ * {@code samMethodType}, as described {@link LambdaMetafactory above}.
+ *
+ * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
+ * will implement {@code Serializable}, and will have a {@code writeReplace}
+ * method that returns an appropriate {@link SerializedLambda}. The
+ * {@code caller} class must have an appropriate {@code $deserializeLambda$}
+ * method, as described in {@link SerializedLambda}.
+ *
+ * <p>When the target of the {@code CallSite} returned from this method is
+ * invoked, the resulting function objects are instances of a class with
+ * the following properties:
+ * <ul>
+ * <li>The class implements the interface named by the return type
+ * of {@code invokedType} and any interfaces named by {@code markerInterfaces}</li>
+ * <li>The class declares methods with the name given by {@code invokedName},
+ * and the signature given by {@code samMethodType} and additional signatures
+ * given by {@code bridges}</li>
+ * <li>The class may override methods from {@code Object}, and may
+ * implement methods related to serialization.</li>
+ * </ul>
+ *
+ * @param caller Represents a lookup context with the accessibility
+ * privileges of the caller. When used with {@code invokedynamic},
+ * this is stacked automatically by the VM.
+ * @param invokedName The name of the method to implement. When used with
+ * {@code invokedynamic}, this is provided by the
+ * {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
+ * @param invokedType The expected signature of the {@code CallSite}. The
+ * parameter types represent the types of capture variables;
+ * the return type is the interface to implement. When
+ * used with {@code invokedynamic}, this is provided by
+ * the {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
* In the event that the implementation method is an
- * instance method, the first argument in the invocation
- * signature will correspond to the receiver.
- * @param args flags and optional arguments, as described above
- * @return a CallSite, which, when invoked, will return an instance of the
- * functional interface
- * @throws ReflectiveOperationException if the caller is not able to
- * reconstruct one of the method handles
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * instance method and this signature has any parameters,
+ * the first parameter in the invocation signature must
+ * correspond to the receiver.
+ * @param args An {@code Object[]} array containing the required
+ * arguments {@code samMethodType}, {@code implMethod},
+ * {@code instantiatedMethodType}, {@code flags}, and any
+ * optional arguments, as described
+ * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above}
+ * @return a CallSite whose target can be used to perform capture, generating
+ * instances of the interface named by {@code invokedType}
+ * @throws LambdaConversionException If any of the linkage invariants
+ * described {@link LambdaMetafactory above}
+ * are violated
*/
public static CallSite altMetafactory(MethodHandles.Lookup caller,
String invokedName,
MethodType invokedType,
Object... args)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
MethodType samMethodType = (MethodType)args[0];
MethodHandle implMethod = (MethodHandle)args[1];
MethodType instantiatedMethodType = (MethodType)args[2];
@@ -294,15 +451,15 @@
else
bridges = EMPTY_MT_ARRAY;
- boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
- for (Class<?> c : markerInterfaces)
- foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
- boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
- || foundSerializableSupertype;
-
- if (isSerializable && !foundSerializableSupertype) {
- markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
- markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+ boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
+ if (isSerializable) {
+ boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
+ for (Class<?> c : markerInterfaces)
+ foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
+ if (!foundSerializableSupertype) {
+ markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
+ markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+ }
}
AbstractValidatingLambdaMetafactory mf
diff --git a/src/share/classes/java/lang/invoke/MagicLambdaImpl.java b/src/share/classes/java/lang/invoke/MagicLambdaImpl.java
deleted file mode 100644
index b78588b..0000000
--- a/src/share/classes/java/lang/invoke/MagicLambdaImpl.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang.invoke;
-
-/** <P> MagicLambdaImpl (named for similarity to MagicAccessorImpl and
- others, not because it actually implements an interface) is a
- marker class in the hierarchy. All subclasses of this class are
- "magically" granted access by the VM to otherwise inaccessible
- fields and methods of other classes. It is distinct from MagicAccessorImpl
- because, while we want to bypass accessibility checks, we do not want to
- bypass verification.</P>
-
- <P> Do not change the name of this class without also changing the
- VM's code. </P> */
-
-class MagicLambdaImpl {
-}
diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
index 56cb245..fd5cac8 100644
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -441,8 +441,13 @@
assert(refKindIsValid(refKind));
return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
} catch (IllegalAccessException ex) {
- Error err = new IllegalAccessError(ex.getMessage());
- throw initCauseFrom(err, ex);
+ Throwable cause = ex.getCause();
+ if (cause instanceof AbstractMethodError) {
+ throw (AbstractMethodError) cause;
+ } else {
+ Error err = new IllegalAccessError(ex.getMessage());
+ throw initCauseFrom(err, ex);
+ }
} catch (NoSuchMethodException ex) {
Error err = new NoSuchMethodError(ex.getMessage());
throw initCauseFrom(err, ex);
diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
index 1ad7e9c..57a6f78 100644
--- a/src/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/share/classes/java/lang/invoke/MethodHandles.java
@@ -1716,6 +1716,13 @@
checkSymbolicClass(defc);
return mh;
}
+ // Treat MethodHandle.invoke and invokeExact specially.
+ if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
+ mh = findVirtualForMH(member.getName(), member.getMethodType());
+ if (mh != null) {
+ return mh;
+ }
+ }
MemberName resolved = resolveOrFail(refKind, member);
mh = getDirectMethodForConstant(refKind, defc, resolved);
if (mh instanceof DirectMethodHandle
@@ -1768,12 +1775,6 @@
if (MethodHandleNatives.refKindIsField(refKind)) {
return getDirectFieldNoSecurityManager(refKind, defc, member);
} else if (MethodHandleNatives.refKindIsMethod(refKind)) {
- if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
- MethodHandle mh = findVirtualForMH(member.getName(), member.getMethodType());
- if (mh != null) {
- return mh;
- }
- }
return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass);
} else if (refKind == REF_newInvokeSpecial) {
return getDirectConstructorNoSecurityManager(defc, member);
diff --git a/src/share/classes/java/lang/invoke/SerializedLambda.java b/src/share/classes/java/lang/invoke/SerializedLambda.java
index 9be96ff..e641201 100644
--- a/src/share/classes/java/lang/invoke/SerializedLambda.java
+++ b/src/share/classes/java/lang/invoke/SerializedLambda.java
@@ -32,9 +32,26 @@
import java.util.Objects;
/**
- * Serialized form of a lambda expression. The properties of this class represent the information that is present
- * at the lambda factory site, including the identity of the primary functional interface method, the identity of the
- * implementation method, and any variables captured from the local environment at the time of lambda capture.
+ * Serialized form of a lambda expression. The properties of this class
+ * represent the information that is present at the lambda factory site, including
+ * static metafactory arguments such as the identity of the primary functional
+ * interface method and the identity of the implementation method, as well as
+ * dynamic metafactory arguments such as values captured from the lexical scope
+ * at the time of lambda capture.
+ *
+ * <p>Implementors of serializable lambdas, such as compilers or language
+ * runtime libraries, are expected to ensure that instances deserialize properly.
+ * One means to do so is to ensure that the {@code writeReplace} method returns
+ * an instance of {@code SerializedLambda}, rather than allowing default
+ * serialization to proceed.
+ *
+ * <p>{@code SerializedLambda} has a {@code readResolve} method that looks for
+ * a (possibly private) static method called
+ * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
+ * that with itself as the first argument, and returns the result. Lambda classes
+ * implementing {@code $deserializeLambda$} are responsible for validating
+ * that the properties of the {@code SerializedLambda} are consistent with a
+ * lambda actually captured by that class.
*
* @see LambdaMetafactory
*/
diff --git a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
index 3aa63c8..f65049d 100644
--- a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
+++ b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
@@ -28,6 +28,7 @@
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
+import sun.invoke.util.BytecodeDescriptor;
import sun.invoke.util.Wrapper;
import static sun.invoke.util.Wrapper.*;
@@ -204,27 +205,27 @@
}
/**
- * Convert an argument of type 'argType' to be passed to 'targetType' assuring that it is 'functionalType'.
+ * Convert an argument of type 'arg' to be passed to 'target' assuring that it is 'functional'.
* Insert the needed conversion instructions in the method code.
- * @param argType
- * @param targetType
- * @param functionalType
+ * @param arg
+ * @param target
+ * @param functional
*/
- void convertType(String dArg, String dTarget, String dFunctional) {
- if (dArg.equals(dTarget)) {
+ void convertType(Class<?> arg, Class<?> target, Class<?> functional) {
+ if (arg.equals(target)) {
return;
}
- Wrapper wArg = toWrapper(dArg);
- Wrapper wTarget = toWrapper(dTarget);
- if (wArg == VOID || wTarget == VOID) {
+ if (arg == Void.TYPE || target == Void.TYPE) {
return;
}
- if (isPrimitive(wArg)) {
- if (isPrimitive(wTarget)) {
+ if (arg.isPrimitive()) {
+ Wrapper wArg = Wrapper.forPrimitiveType(arg);
+ if (target.isPrimitive()) {
// Both primitives: widening
- widen(wArg, wTarget);
+ widen(wArg, Wrapper.forPrimitiveType(target));
} else {
// Primitive argument to reference target
+ String dTarget = BytecodeDescriptor.unparse(target);
Wrapper wPrimTarget = wrapperOrNullFromDescriptor(dTarget);
if (wPrimTarget != null) {
// The target is a boxed primitive type, widen to get there before boxing
@@ -237,16 +238,18 @@
}
}
} else {
+ String dArg = BytecodeDescriptor.unparse(arg);
String dSrc;
- Wrapper wFunctional = toWrapper(dFunctional);
- if (isPrimitive(wFunctional)) {
+ if (functional.isPrimitive()) {
dSrc = dArg;
} else {
// Cast to convert to possibly more specific type, and generate CCE for invalid arg
- dSrc = dFunctional;
- cast(dArg, dFunctional);
+ dSrc = BytecodeDescriptor.unparse(functional);
+ cast(dArg, dSrc);
}
- if (isPrimitive(wTarget)) {
+ String dTarget = BytecodeDescriptor.unparse(target);
+ if (target.isPrimitive()) {
+ Wrapper wTarget = toWrapper(dTarget);
// Reference argument to primitive target
Wrapper wps = wrapperOrNullFromDescriptor(dSrc);
if (wps != null) {
diff --git a/src/share/classes/java/lang/management/ManagementFactory.java b/src/share/classes/java/lang/management/ManagementFactory.java
index 6e00706..0c7297a 100644
--- a/src/share/classes/java/lang/management/ManagementFactory.java
+++ b/src/share/classes/java/lang/management/ManagementFactory.java
@@ -60,7 +60,7 @@
* one or more <i>platform MXBeans</i> representing
* the management interface of a component of the Java virtual
* machine.
- * <p>
+ *
* <h3><a name="MXBean">Platform MXBeans</a></h3>
* <p>
* A platform MXBean is a <i>managed bean</i> that
diff --git a/src/share/classes/java/lang/management/ManagementPermission.java b/src/share/classes/java/lang/management/ManagementPermission.java
index 7f62c5e..ae3dc56 100644
--- a/src/share/classes/java/lang/management/ManagementPermission.java
+++ b/src/share/classes/java/lang/management/ManagementPermission.java
@@ -33,10 +33,8 @@
* The following table
* provides a summary description of what the permission allows,
* and discusses the risks of granting code the permission.
- * <P>
*
- * <table border=1 cellpadding=5 summary="Table shows permission target name, wh
-at the permission allows, and associated risks">
+ * <table border=1 cellpadding=5 summary="Table shows permission target name, what the permission allows, and associated risks">
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
diff --git a/src/share/classes/java/lang/management/MemoryUsage.java b/src/share/classes/java/lang/management/MemoryUsage.java
index bbb75a2..6d11e32 100644
--- a/src/share/classes/java/lang/management/MemoryUsage.java
+++ b/src/share/classes/java/lang/management/MemoryUsage.java
@@ -79,7 +79,7 @@
* </table>
*
* Below is a picture showing an example of a memory pool:
- * <p>
+ *
* <pre>
* +----------------------------------------------+
* +//////////////// | +
@@ -250,7 +250,7 @@
* Returns a <tt>MemoryUsage</tt> object represented by the
* given <tt>CompositeData</tt>. The given <tt>CompositeData</tt>
* must contain the following attributes:
- * <p>
+ *
* <blockquote>
* <table border summary="The attributes and the types the given CompositeData contains">
* <tr>
diff --git a/src/share/classes/java/lang/management/package.html b/src/share/classes/java/lang/management/package.html
index 7d2fa99..c2c74d0 100644
--- a/src/share/classes/java/lang/management/package.html
+++ b/src/share/classes/java/lang/management/package.html
@@ -82,7 +82,7 @@
<b>1. Direct access to an MXBean interface</b>
<p>
<ul>
-<li>Get an MXBean instance locally in the running Java virtual machine:<p>
+<li>Get an MXBean instance locally in the running Java virtual machine:
<pre>
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
@@ -103,7 +103,7 @@
<p>
</li>
<li>Construct an MXBean proxy instance that forwards the
- method calls to a given MBeanServer:<p>
+ method calls to a given MBeanServer:
<pre>
MBeanServerConnection mbs;
diff --git a/src/share/classes/java/lang/reflect/AnnotatedElement.java b/src/share/classes/java/lang/reflect/AnnotatedElement.java
index 50a7e6a..f169202 100644
--- a/src/share/classes/java/lang/reflect/AnnotatedElement.java
+++ b/src/share/classes/java/lang/reflect/AnnotatedElement.java
@@ -27,6 +27,15 @@
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
+import java.lang.annotation.Repeatable;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.AnnotationType;
/**
* Represents an annotated element of the program currently running in this
@@ -222,6 +231,18 @@
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
+ * @implSpec The default implementation first calls {@link
+ * #getDeclaredAnnotationsByType(Class)} passing {@code
+ * annotationClass} as the argument. If the returned array has
+ * length greater than zero, the array is returned. If the returned
+ * array is zero-length and this {@code AnnotatedElement} is a
+ * class and the argument type is an inheritable annotation type,
+ * and the superclass of this {@code AnnotatedElement} is non-null,
+ * then the returned result is the result of calling {@link
+ * #getAnnotationsByType(Class)} on the superclass with {@code
+ * annotationClass} as the argument. Otherwise, a zero-length
+ * array is returned.
+ *
* @param <T> the type of the annotation to query for and return if present
* @param annotationClass the Class object corresponding to the
* annotation type
@@ -230,7 +251,29 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
+ default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ /*
+ * Definition of associated: directly or indirectly present OR
+ * neither directly nor indirectly present AND the element is
+ * a Class, the annotation type is inheritable, and the
+ * annotation type is associated with the superclass of the
+ * element.
+ */
+ T[] result = getDeclaredAnnotationsByType(annotationClass);
+
+ if (result.length == 0 && // Neither directly nor indirectly present
+ this instanceof Class && // the element is a class
+ AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
+ Class<?> superClass = ((Class<?>) this).getSuperclass();
+ if (superClass != null) {
+ // Determine if the annotation is associated with the
+ // superclass
+ result = superClass.getAnnotationsByType(annotationClass);
+ }
+ }
+
+ return result;
+ }
/**
* Returns this element's annotation for the specified type if
@@ -239,6 +282,11 @@
* This method ignores inherited annotations. (Returns null if no
* annotations are directly present on this element.)
*
+ * @implSpec The default implementation first performs a null check
+ * and then loops over the results of {@link
+ * #getDeclaredAnnotations} returning the first annotation whose
+ * annotation type matches the argument type.
+ *
* @param <T> the type of the annotation to query for and return if directly present
* @param annotationClass the Class object corresponding to the
* annotation type
@@ -247,7 +295,18 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
+ default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ // Loop over all directly-present annotations looking for a matching one
+ for (Annotation annotation : getDeclaredAnnotations()) {
+ if (annotationClass.equals(annotation.annotationType())) {
+ // More robust to do a dynamic cast at runtime instead
+ // of compile-time only.
+ return annotationClass.cast(annotation);
+ }
+ }
+ return null;
+ }
/**
* Returns this element's annotation(s) for the specified type if
@@ -268,6 +327,22 @@
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
+ * @implSpec The default implementation may call {@link
+ * #getDeclaredAnnotation(Class)} one or more times to find a
+ * directly present annotation and, if the annotation type is
+ * repeatable, to find a container annotation. If annotations of
+ * the annotation type {@code annotationClass} are found to be both
+ * directly and indirectly present, then {@link
+ * #getDeclaredAnnotations()} will get called to determine the
+ * order of the elements in the returned array.
+ *
+ * <p>Alternatively, the default implementation may call {@link
+ * #getDeclaredAnnotations()} a single time and the returned array
+ * examined for both directly and indirectly present
+ * annotations. The results of calling {@link
+ * #getDeclaredAnnotations()} are assumed to be consistent with the
+ * results of calling {@link #getDeclaredAnnotation(Class)}.
+ *
* @param <T> the type of the annotation to query for and return
* if directly or indirectly present
* @param annotationClass the Class object corresponding to the
@@ -277,7 +352,16 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
+ default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ return AnnotationSupport.
+ getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).
+ collect(Collectors.toMap(Annotation::annotationType,
+ Function.identity(),
+ ((first,second) -> first),
+ LinkedHashMap::new)),
+ annotationClass);
+ }
/**
* Returns annotations that are <em>directly present</em> on this element.
diff --git a/src/share/classes/java/lang/reflect/Constructor.java b/src/share/classes/java/lang/reflect/Constructor.java
index 202a736..d852fcd 100644
--- a/src/share/classes/java/lang/reflect/Constructor.java
+++ b/src/share/classes/java/lang/reflect/Constructor.java
@@ -28,6 +28,8 @@
import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection;
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
@@ -534,4 +536,22 @@
public AnnotatedType getAnnotatedReturnType() {
return getAnnotatedReturnType0(getDeclaringClass());
}
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public AnnotatedType getAnnotatedReceiverType() {
+ if (getDeclaringClass().getEnclosingClass() == null)
+ return super.getAnnotatedReceiverType();
+
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getDeclaringClass().getEnclosingClass(),
+ TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
+ }
}
diff --git a/src/share/classes/java/lang/reflect/Executable.java b/src/share/classes/java/lang/reflect/Executable.java
index c92c9a5..d033e7e 100644
--- a/src/share/classes/java/lang/reflect/Executable.java
+++ b/src/share/classes/java/lang/reflect/Executable.java
@@ -383,7 +383,7 @@
private transient volatile Parameter[] parameters;
private native Parameter[] getParameters0();
- private native byte[] getTypeAnnotationBytes0();
+ native byte[] getTypeAnnotationBytes0();
// Needed by reflectaccess
byte[] getTypeAnnotationBytes() {
@@ -527,7 +527,7 @@
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff --git a/src/share/classes/java/lang/reflect/Field.java b/src/share/classes/java/lang/reflect/Field.java
index e84b6b2..6e243bc 100644
--- a/src/share/classes/java/lang/reflect/Field.java
+++ b/src/share/classes/java/lang/reflect/Field.java
@@ -1123,7 +1123,7 @@
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff --git a/src/share/classes/java/lang/reflect/Parameter.java b/src/share/classes/java/lang/reflect/Parameter.java
index 2285819..d8c992c 100644
--- a/src/share/classes/java/lang/reflect/Parameter.java
+++ b/src/share/classes/java/lang/reflect/Parameter.java
@@ -295,7 +295,7 @@
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff --git a/src/share/classes/java/lang/reflect/ReflectPermission.java b/src/share/classes/java/lang/reflect/ReflectPermission.java
index 6570e79..2674de4 100644
--- a/src/share/classes/java/lang/reflect/ReflectPermission.java
+++ b/src/share/classes/java/lang/reflect/ReflectPermission.java
@@ -31,7 +31,6 @@
* The following table
* provides a summary description of what the permission allows,
* and discusses the risks of granting code the permission.
- * <P>
*
* <table border=1 cellpadding=5 summary="Table shows permission target name, what the permission allows, and associated risks">
* <tr>
diff --git a/src/share/classes/java/math/BigInteger.java b/src/share/classes/java/math/BigInteger.java
index f7878ab..5fab744 100644
--- a/src/share/classes/java/math/BigInteger.java
+++ b/src/share/classes/java/math/BigInteger.java
@@ -97,6 +97,21 @@
* {@code NullPointerException} when passed
* a null object reference for any input parameter.
*
+ * BigInteger must support values in the range
+ * -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
+ * +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive)
+ * and may support values outside of that range.
+ *
+ * The range of probable prime values is limited and may be less than
+ * the full supported positive range of {@code BigInteger}.
+ * The range must be at least 1 to 2<sup>500000000</sup>.
+ *
+ * @implNote
+ * BigInteger constructors and operations throw {@code ArithmeticException} when
+ * the result is out of the supported range of
+ * -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
+ * +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive).
+ *
* @see BigDecimal
* @author Josh Bloch
* @author Michael McCloskey
@@ -183,6 +198,18 @@
final static long LONG_MASK = 0xffffffffL;
/**
+ * This constant limits {@code mag.length} of BigIntegers to the supported
+ * range.
+ */
+ private static final int MAX_MAG_LENGTH = Integer.MAX_VALUE / Integer.SIZE + 1; // (1 << 26)
+
+ /**
+ * Bit lengths larger than this constant can cause overflow in searchLen
+ * calculation and in BitSieve.singleSearch method.
+ */
+ private static final int PRIME_SEARCH_BIT_LENGTH_LIMIT = 500000000;
+
+ /**
* The threshold value for using Karatsuba multiplication. If the number
* of ints in both mag arrays are greater than this number, then
* Karatsuba multiplication will be used. This value is found
@@ -256,6 +283,9 @@
mag = stripLeadingZeroBytes(val);
signum = (mag.length == 0 ? 0 : 1);
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -275,6 +305,9 @@
mag = trustedStripLeadingZeroInts(val);
signum = (mag.length == 0 ? 0 : 1);
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -306,6 +339,9 @@
throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum;
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -327,6 +363,9 @@
throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum;
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -359,17 +398,20 @@
int sign = 1;
int index1 = val.lastIndexOf('-');
int index2 = val.lastIndexOf('+');
- if ((index1 + index2) <= -1) {
- // No leading sign character or at most one leading sign character
- if (index1 == 0 || index2 == 0) {
- cursor = 1;
- if (len == 1)
- throw new NumberFormatException("Zero length BigInteger");
+ if (index1 >= 0) {
+ if (index1 != 0 || index2 >= 0) {
+ throw new NumberFormatException("Illegal embedded sign character");
}
- if (index1 == 0)
- sign = -1;
- } else
- throw new NumberFormatException("Illegal embedded sign character");
+ sign = -1;
+ cursor = 1;
+ } else if (index2 >= 0) {
+ if (index2 != 0) {
+ throw new NumberFormatException("Illegal embedded sign character");
+ }
+ cursor = 1;
+ }
+ if (cursor == len)
+ throw new NumberFormatException("Zero length BigInteger");
// Skip leading zeros and compute number of digits in magnitude
while (cursor < len &&
@@ -388,8 +430,11 @@
// Pre-allocate array of expected size. May be too large but can
// never be too small. Typically exact.
- int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
- int numWords = (numBits + 31) >>> 5;
+ long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
+ if (numBits + 31 >= (1L << 32)) {
+ reportOverflow();
+ }
+ int numWords = (int) (numBits + 31) >>> 5;
int[] magnitude = new int[numWords];
// Process first (potentially short) digit group
@@ -413,6 +458,9 @@
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/*
@@ -439,8 +487,11 @@
if (len < 10) {
numWords = 1;
} else {
- int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1);
- numWords = (numBits + 31) >>> 5;
+ long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1;
+ if (numBits + 31 >= (1L << 32)) {
+ reportOverflow();
+ }
+ numWords = (int) (numBits + 31) >>> 5;
}
int[] magnitude = new int[numWords];
@@ -456,6 +507,9 @@
destructiveMulAdd(magnitude, intRadix[10], groupVal);
}
mag = trustedStripLeadingZeroInts(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
// Create an integer with the digits between the two indexes
@@ -575,7 +629,7 @@
* this constructor is proportional to the value of this parameter.
* @param rnd source of random bits used to select candidates to be
* tested for primality.
- * @throws ArithmeticException {@code bitLength < 2}.
+ * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength()
*/
public BigInteger(int bitLength, int certainty, Random rnd) {
@@ -607,7 +661,7 @@
* @param rnd source of random bits used to select candidates to be
* tested for primality.
* @return a BigInteger of {@code bitLength} bits that is probably prime
- * @throws ArithmeticException {@code bitLength < 2}.
+ * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength()
* @since 1.4
*/
@@ -677,7 +731,7 @@
p.mag[p.mag.length-1] &= 0xfffffffe;
// Use a sieve length likely to contain the next prime number
- int searchLen = (bitLength / 20) * 64;
+ int searchLen = getPrimeSearchLen(bitLength);
BitSieve searchSieve = new BitSieve(p, searchLen);
BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
@@ -701,7 +755,7 @@
*
* @return the first integer greater than this {@code BigInteger} that
* is probably prime.
- * @throws ArithmeticException {@code this < 0}.
+ * @throws ArithmeticException {@code this < 0} or {@code this} is too large.
* @since 1.5
*/
public BigInteger nextProbablePrime() {
@@ -750,7 +804,7 @@
result = result.subtract(ONE);
// Looking for the next large prime
- int searchLen = (result.bitLength() / 20) * 64;
+ int searchLen = getPrimeSearchLen(result.bitLength());
while (true) {
BitSieve searchSieve = new BitSieve(result, searchLen);
@@ -762,6 +816,13 @@
}
}
+ private static int getPrimeSearchLen(int bitLength) {
+ if (bitLength > PRIME_SEARCH_BIT_LENGTH_LIMIT + 1) {
+ throw new ArithmeticException("Prime search implementation restriction on bitLength");
+ }
+ return bitLength / 20 * 64;
+ }
+
/**
* Returns {@code true} if this BigInteger is probably prime,
* {@code false} if it's definitely composite.
@@ -965,6 +1026,9 @@
BigInteger(int[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = magnitude;
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -974,6 +1038,25 @@
private BigInteger(byte[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = stripLeadingZeroBytes(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
+ }
+
+ /**
+ * Throws an {@code ArithmeticException} if the {@code BigInteger} would be
+ * out of the supported range.
+ *
+ * @throws ArithmeticException if {@code this} exceeds the supported range.
+ */
+ private void checkRange() {
+ if (mag.length > MAX_MAG_LENGTH || mag.length == MAX_MAG_LENGTH && mag[0] < 0) {
+ reportOverflow();
+ }
+ }
+
+ private static void reportOverflow() {
+ throw new ArithmeticException("BigInteger would overflow supported range");
}
//Static Factory Methods
@@ -2073,6 +2156,10 @@
// The remaining part can then be exponentiated faster. The
// powers of two will be multiplied back at the end.
int powersOfTwo = partToSquare.getLowestSetBit();
+ long bitsToShift = (long)powersOfTwo * exponent;
+ if (bitsToShift > Integer.MAX_VALUE) {
+ reportOverflow();
+ }
int remainingBits;
@@ -2126,11 +2213,10 @@
// Multiply back the powers of two (quickly, by shifting left)
if (powersOfTwo > 0) {
- int bitsToShift = powersOfTwo*exponent;
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
return valueOf((result << bitsToShift) * newSign);
} else {
- return valueOf(result*newSign).shiftLeft(bitsToShift);
+ return valueOf(result*newSign).shiftLeft((int) bitsToShift);
}
}
else {
@@ -2375,8 +2461,17 @@
BigInteger y1 = m2.modInverse(m1);
BigInteger y2 = m1.modInverse(m2);
- result = a1.multiply(m2).multiply(y1).add
- (a2.multiply(m1).multiply(y2)).mod(m);
+ if (m.mag.length < MAX_MAG_LENGTH / 2) {
+ result = a1.multiply(m2).multiply(y1).add(a2.multiply(m1).multiply(y2)).mod(m);
+ } else {
+ MutableBigInteger t1 = new MutableBigInteger();
+ new MutableBigInteger(a1.multiply(m2)).multiply(new MutableBigInteger(y1), t1);
+ MutableBigInteger t2 = new MutableBigInteger();
+ new MutableBigInteger(a2.multiply(m1)).multiply(new MutableBigInteger(y2), t2);
+ t1.add(t2);
+ MutableBigInteger q = new MutableBigInteger();
+ result = t1.divide(new MutableBigInteger(m), q).toBigInteger();
+ }
}
return (invertResult ? result.modInverse(m) : result);
@@ -2797,27 +2892,31 @@
*
* @param n shift distance, in bits.
* @return {@code this << n}
- * @throws ArithmeticException if the shift distance is {@code
- * Integer.MIN_VALUE}.
* @see #shiftRight
*/
public BigInteger shiftLeft(int n) {
if (signum == 0)
return ZERO;
- if (n == 0)
+ if (n > 0) {
+ return new BigInteger(shiftLeft(mag, n), signum);
+ } else if (n == 0) {
return this;
- if (n < 0) {
- if (n == Integer.MIN_VALUE) {
- throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
- } else {
- return shiftRight(-n);
- }
+ } else {
+ // Possible int overflow in (-n) is not a trouble,
+ // because shiftRightImpl considers its argument unsigned
+ return shiftRightImpl(-n);
}
- int[] newMag = shiftLeft(mag, n);
-
- return new BigInteger(newMag, signum);
}
+ /**
+ * Returns a magnitude array whose value is {@code (mag << n)}.
+ * The shift distance, {@code n}, is considered unnsigned.
+ * (Computes <tt>this * 2<sup>n</sup></tt>.)
+ *
+ * @param mag magnitude, the most-significant int ({@code mag[0]}) must be non-zero.
+ * @param n unsigned shift distance, in bits.
+ * @return {@code mag << n}
+ */
private static int[] shiftLeft(int[] mag, int n) {
int nInts = n >>> 5;
int nBits = n & 0x1f;
@@ -2853,21 +2952,31 @@
*
* @param n shift distance, in bits.
* @return {@code this >> n}
- * @throws ArithmeticException if the shift distance is {@code
- * Integer.MIN_VALUE}.
* @see #shiftLeft
*/
public BigInteger shiftRight(int n) {
- if (n == 0)
+ if (signum == 0)
+ return ZERO;
+ if (n > 0) {
+ return shiftRightImpl(n);
+ } else if (n == 0) {
return this;
- if (n < 0) {
- if (n == Integer.MIN_VALUE) {
- throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
- } else {
- return shiftLeft(-n);
- }
+ } else {
+ // Possible int overflow in {@code -n} is not a trouble,
+ // because shiftLeft considers its argument unsigned
+ return new BigInteger(shiftLeft(mag, -n), signum);
}
+ }
+ /**
+ * Returns a BigInteger whose value is {@code (this >> n)}. The shift
+ * distance, {@code n}, is considered unsigned.
+ * (Computes <tt>floor(this * 2<sup>-n</sup>)</tt>.)
+ *
+ * @param n unsigned shift distance, in bits.
+ * @return {@code this >> n}
+ */
+ private BigInteger shiftRightImpl(int n) {
int nInts = n >>> 5;
int nBits = n & 0x1f;
int magLen = mag.length;
@@ -3899,7 +4008,7 @@
;
int extraByte = (k == byteLength) ? 1 : 0;
- int intLength = ((byteLength - keep + extraByte) + 3)/4;
+ int intLength = ((byteLength - keep + extraByte) + 3) >>> 2;
int result[] = new int[intLength];
/* Copy one's complement of input into output, leaving extra
@@ -4135,7 +4244,8 @@
message = "BigInteger: Signum not present in stream";
throw new java.io.StreamCorruptedException(message);
}
- if ((magnitude.length == 0) != (sign == 0)) {
+ int[] mag = stripLeadingZeroBytes(magnitude);
+ if ((mag.length == 0) != (sign == 0)) {
String message = "BigInteger: signum-magnitude mismatch";
if (fields.defaulted("magnitude"))
message = "BigInteger: Magnitude not present in stream";
@@ -4146,7 +4256,14 @@
UnsafeHolder.putSign(this, sign);
// Calculate mag field from magnitude and discard magnitude
- UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude));
+ UnsafeHolder.putMag(this, mag);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ try {
+ checkRange();
+ } catch (ArithmeticException e) {
+ throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
+ }
+ }
}
// Support for resetting final fields while deserializing
diff --git a/src/share/classes/java/math/MutableBigInteger.java b/src/share/classes/java/math/MutableBigInteger.java
index 6f72f2d..bc4e484 100644
--- a/src/share/classes/java/math/MutableBigInteger.java
+++ b/src/share/classes/java/math/MutableBigInteger.java
@@ -1257,14 +1257,14 @@
int j = (s+m-1) / m; // step 2a: j = ceil(s/m)
int n = j * m; // step 2b: block length in 32-bit units
- int n32 = 32 * n; // block length in bits
- int sigma = Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
+ long n32 = 32L * n; // block length in bits
+ int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
MutableBigInteger bShifted = new MutableBigInteger(b);
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
safeLeftShift(sigma); // step 4b: shift this by the same amount
// step 5: t is the number of blocks needed to accommodate this plus one additional bit
- int t = (bitLength()+n32) / n32;
+ int t = (int) ((bitLength()+n32) / n32);
if (t < 2) {
t = 2;
}
@@ -1421,10 +1421,10 @@
}
/** @see BigInteger#bitLength() */
- int bitLength() {
+ long bitLength() {
if (intLen == 0)
return 0;
- return intLen*32 - Integer.numberOfLeadingZeros(value[offset]);
+ return intLen*32L - Integer.numberOfLeadingZeros(value[offset]);
}
/**
diff --git a/src/share/classes/java/net/DatagramSocket.java b/src/share/classes/java/net/DatagramSocket.java
index d779a3b..1e095de 100644
--- a/src/share/classes/java/net/DatagramSocket.java
+++ b/src/share/classes/java/net/DatagramSocket.java
@@ -196,7 +196,7 @@
* socket address.
* <p>
* If, if the address is {@code null}, creates an unbound socket.
- * <p>
+ *
* <p>If there is a security manager,
* its {@code checkListen} method is first called
* with the port from the socket address
@@ -1109,7 +1109,7 @@
* represent the value of the TOS octet in IP packets sent by
* the socket.
* RFC 1349 defines the TOS values as follows:
- * <p>
+ *
* <UL>
* <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
* <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
diff --git a/src/share/classes/java/net/HttpCookie.java b/src/share/classes/java/net/HttpCookie.java
index fb02ae3..0017712 100644
--- a/src/share/classes/java/net/HttpCookie.java
+++ b/src/share/classes/java/net/HttpCookie.java
@@ -761,7 +761,7 @@
// from RFC 2068, token special case characters
//
// private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
- private static final String tspecials = ",;";
+ private static final String tspecials = ",; "; // deliberately includes space
/*
* Tests a string and returns true if the string counts as a token.
diff --git a/src/share/classes/java/net/Inet6Address.java b/src/share/classes/java/net/Inet6Address.java
index 068a4ce..001c55f 100644
--- a/src/share/classes/java/net/Inet6Address.java
+++ b/src/share/classes/java/net/Inet6Address.java
@@ -133,7 +133,7 @@
* representation. However, it will be converted into an IPv4
* address.</td></tr>
* </table></blockquote>
- * <p>
+ *
* <h4><A NAME="scoped">Textual representation of IPv6 scoped addresses</a></h4>
*
* <p> The textual representation of IPv6 addresses as described above can be
@@ -150,11 +150,11 @@
*
* <p> The general format for specifying the <i>scope_id</i> is the following:
*
- * <p><blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote>
+ * <blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote>
* <p> The IPv6-address is a literal IPv6 address as described above.
* The <i>scope_id</i> refers to an interface on the local system, and it can be
* specified in two ways.
- * <p><ol><li><i>As a numeric identifier.</i> This must be a positive integer
+ * <ol><li><i>As a numeric identifier.</i> This must be a positive integer
* that identifies the particular interface and scope as understood by the
* system. Usually, the numeric values can be determined through administration
* tools on the system. Each interface may have multiple values, one for each
diff --git a/src/share/classes/java/net/MulticastSocket.java b/src/share/classes/java/net/MulticastSocket.java
index 9c5cb05..1d42dfe 100644
--- a/src/share/classes/java/net/MulticastSocket.java
+++ b/src/share/classes/java/net/MulticastSocket.java
@@ -140,7 +140,7 @@
* Create a MulticastSocket bound to the specified socket address.
* <p>
* Or, if the address is {@code null}, create an unbound socket.
- * <p>
+ *
* <p>If there is a security manager,
* its {@code checkListen} method is first called
* with the SocketAddress port as its argument to ensure the operation is allowed.
diff --git a/src/share/classes/java/net/NetPermission.java b/src/share/classes/java/net/NetPermission.java
index cf7cbd2..9178f34 100644
--- a/src/share/classes/java/net/NetPermission.java
+++ b/src/share/classes/java/net/NetPermission.java
@@ -46,7 +46,6 @@
* The following table lists all the possible NetPermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- * <P>
*
* <table border=1 cellpadding=5 summary="Permission target name, what the permission allows, and associated risks">
* <tr>
diff --git a/src/share/classes/java/net/Proxy.java b/src/share/classes/java/net/Proxy.java
index fe481fa..8ba020e 100644
--- a/src/share/classes/java/net/Proxy.java
+++ b/src/share/classes/java/net/Proxy.java
@@ -66,8 +66,8 @@
* Used, for instance, to create sockets bypassing any other global
* proxy settings (like SOCKS):
* <P>
- * {@code Socket s = new Socket(Proxy.NO_PROXY);}<br>
- * <P>
+ * {@code Socket s = new Socket(Proxy.NO_PROXY);}
+ *
*/
public final static Proxy NO_PROXY = new Proxy();
diff --git a/src/share/classes/java/net/Socket.java b/src/share/classes/java/net/Socket.java
index 3612603..21cf5aa 100644
--- a/src/share/classes/java/net/Socket.java
+++ b/src/share/classes/java/net/Socket.java
@@ -1230,13 +1230,13 @@
* Generally, the window size can be modified at any time when a socket is
* connected. However, if a receive window larger than 64K is required then
* this must be requested <B>before</B> the socket is connected to the
- * remote peer. There are two cases to be aware of:<p>
+ * remote peer. There are two cases to be aware of:
* <ol>
* <li>For sockets accepted from a ServerSocket, this must be done by calling
* {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket
* is bound to a local address.<p></li>
* <li>For client sockets, setReceiveBufferSize() must be called before
- * connecting the socket to its remote peer.<p></li></ol>
+ * connecting the socket to its remote peer.</li></ol>
* @param size the size to which to set the receive buffer
* size. This value must be greater than 0.
*
@@ -1329,7 +1329,7 @@
* represent the value of the TOS octet in IP packets sent by
* the socket.
* RFC 1349 defines the TOS values as follows:
- * <p>
+ *
* <UL>
* <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
* <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
diff --git a/src/share/classes/java/net/SocketOptions.java b/src/share/classes/java/net/SocketOptions.java
index b9508db..7e1b0fc 100644
--- a/src/share/classes/java/net/SocketOptions.java
+++ b/src/share/classes/java/net/SocketOptions.java
@@ -134,7 +134,7 @@
* previously written data.
*<P>
* Valid for TCP only: SocketImpl.
- * <P>
+ *
* @see Socket#setTcpNoDelay
* @see Socket#getTcpNoDelay
*/
@@ -155,7 +155,7 @@
* This option <B>must</B> be specified in the constructor.
* <P>
* Valid for: SocketImpl, DatagramSocketImpl
- * <P>
+ *
* @see Socket#getLocalAddress
* @see DatagramSocket#getLocalAddress
*/
@@ -186,7 +186,7 @@
* want to use other than the system default. Takes/returns an InetAddress.
* <P>
* Valid for Multicast: DatagramSocketImpl
- * <P>
+ *
* @see MulticastSocket#setInterface(InetAddress)
* @see MulticastSocket#getInterface()
*/
diff --git a/src/share/classes/java/net/SocketPermission.java b/src/share/classes/java/net/SocketPermission.java
index e90856e..1b11437 100644
--- a/src/share/classes/java/net/SocketPermission.java
+++ b/src/share/classes/java/net/SocketPermission.java
@@ -779,27 +779,27 @@
* specified permission.
* <P>
* More specifically, this method first ensures that all of the following
- * are true (and returns false if any of them are not):<p>
+ * are true (and returns false if any of them are not):
* <ul>
- * <li> <i>p</i> is an instanceof SocketPermission,<p>
+ * <li> <i>p</i> is an instanceof SocketPermission,
* <li> <i>p</i>'s actions are a proper subset of this
- * object's actions, and<p>
+ * object's actions, and
* <li> <i>p</i>'s port range is included in this port range. Note:
- * port range is ignored when p only contains the action, 'resolve'.<p>
+ * port range is ignored when p only contains the action, 'resolve'.
* </ul>
*
* Then {@code implies} checks each of the following, in order,
- * and for each returns true if the stated condition is true:<p>
+ * and for each returns true if the stated condition is true:
* <ul>
* <li> If this object was initialized with a single IP address and one of <i>p</i>'s
- * IP addresses is equal to this object's IP address.<p>
+ * IP addresses is equal to this object's IP address.
* <li>If this object is a wildcard domain (such as *.sun.com), and
* <i>p</i>'s canonical name (the name without any preceding *)
* ends with this object's canonical host name. For example, *.sun.com
- * implies *.eng.sun.com..<p>
+ * implies *.eng.sun.com.
* <li>If this object was not initialized with a single IP address, and one of this
- * object's IP addresses equals one of <i>p</i>'s IP addresses.<p>
- * <li>If this canonical name equals <i>p</i>'s canonical name.<p>
+ * object's IP addresses equals one of <i>p</i>'s IP addresses.
+ * <li>If this canonical name equals <i>p</i>'s canonical name.
* </ul>
*
* If none of the above are true, {@code implies} returns false.
diff --git a/src/share/classes/java/net/URI.java b/src/share/classes/java/net/URI.java
index 71c4f6d..813de5c 100644
--- a/src/share/classes/java/net/URI.java
+++ b/src/share/classes/java/net/URI.java
@@ -389,20 +389,20 @@
* colon following a host name but no port (as in
* {@code http://java.sun.com:} ), and that does not encode characters
* except those that must be quoted, the following identities also hold:
- * <p><pre>
+ * <pre>
* new URI(<i>u</i>.getScheme(),
* <i>u</i>.getSchemeSpecificPart(),
* <i>u</i>.getFragment())
* .equals(<i>u</i>)</pre>
* in all cases,
- * <p><pre>
+ * <pre>
* new URI(<i>u</i>.getScheme(),
* <i>u</i>.getUserInfo(), <i>u</i>.getAuthority(),
* <i>u</i>.getPath(), <i>u</i>.getQuery(),
* <i>u</i>.getFragment())
* .equals(<i>u</i>)</pre>
* if <i>u</i> is hierarchical, and
- * <p><pre>
+ * <pre>
* new URI(<i>u</i>.getScheme(),
* <i>u</i>.getUserInfo(), <i>u</i>.getHost(), <i>u</i>.getPort(),
* <i>u</i>.getPath(), <i>u</i>.getQuery(),
diff --git a/src/share/classes/java/net/URLClassLoader.java b/src/share/classes/java/net/URLClassLoader.java
index 7487485..f272346 100644
--- a/src/share/classes/java/net/URLClassLoader.java
+++ b/src/share/classes/java/net/URLClassLoader.java
@@ -25,21 +25,30 @@
package java.net;
-import java.io.*;
-import java.util.*;
-import java.util.jar.Manifest;
-import java.util.jar.JarFile;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.security.CodeSigner;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.AccessController;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
import java.security.AccessControlContext;
-import java.security.SecureClassLoader;
+import java.security.AccessController;
+import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.net.www.ParseUtil;
@@ -84,6 +93,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent) {
@@ -127,6 +137,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls) {
@@ -169,6 +180,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent,
@@ -260,13 +272,13 @@
* and errors are not caught. Calling close on an already closed
* loader has no effect.
* <p>
- * @throws IOException if closing any file opened by this class loader
+ * @exception IOException if closing any file opened by this class loader
* resulted in an IOException. Any such exceptions are caught internally.
* If only one is caught, then it is re-thrown. If more than one exception
* is caught, then the second and following exceptions are added
* as suppressed exceptions of the first one caught, which is then re-thrown.
*
- * @throws SecurityException if a security manager is set, and it denies
+ * @exception SecurityException if a security manager is set, and it denies
* {@link RuntimePermission}{@code ("closeClassLoader")}
*
* @since 1.7
@@ -339,6 +351,7 @@
* @return the resulting class
* @exception ClassNotFoundException if the class could not be found,
* or if the loader is closed.
+ * @exception NullPointerException if {@code name} is {@code null}.
*/
protected Class<?> findClass(final String name)
throws ClassNotFoundException
@@ -621,6 +634,7 @@
* If the protocol is not "file", then permission
* to connect to and accept connections from the URL's host is granted.
* @param codesource the codesource
+ * @exception NullPointerException if {@code codesource} is {@code null}.
* @return the permissions granted to the codesource
*/
protected PermissionCollection getPermissions(CodeSource codesource)
@@ -700,6 +714,7 @@
*
* @param urls the URLs to search for classes and resources
* @param parent the parent class loader for delegation
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls,
@@ -725,6 +740,7 @@
* loading the class.
*
* @param urls the URLs to search for classes and resources
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls) {
diff --git a/src/share/classes/java/net/URLConnection.java b/src/share/classes/java/net/URLConnection.java
index 8393ced..dd66ed2 100644
--- a/src/share/classes/java/net/URLConnection.java
+++ b/src/share/classes/java/net/URLConnection.java
@@ -45,7 +45,7 @@
* application and a URL. Instances of this class can be used both to
* read from and to write to the resource referenced by the URL. In
* general, creating a connection to a URL is a multistep process:
- * <p>
+ *
* <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
* <tr><th>{@code openConnection()}</th>
* <th>{@code connect()}</th></tr>
diff --git a/src/share/classes/java/net/URLDecoder.java b/src/share/classes/java/net/URLDecoder.java
index a0344dc..1e1138a 100644
--- a/src/share/classes/java/net/URLDecoder.java
+++ b/src/share/classes/java/net/URLDecoder.java
@@ -43,7 +43,7 @@
* as the start of a special escaped sequence.
* <p>
* The following rules are applied in the conversion:
- * <p>
+ *
* <ul>
* <li>The alphanumeric characters "{@code a}" through
* "{@code z}", "{@code A}" through
diff --git a/src/share/classes/java/net/URLEncoder.java b/src/share/classes/java/net/URLEncoder.java
index a39d4e4..86377b7 100644
--- a/src/share/classes/java/net/URLEncoder.java
+++ b/src/share/classes/java/net/URLEncoder.java
@@ -49,7 +49,6 @@
* <p>
* When encoding a String, the following rules apply:
*
- * <p>
* <ul>
* <li>The alphanumeric characters "{@code a}" through
* "{@code z}", "{@code A}" through
diff --git a/src/share/classes/java/net/URLPermission.java b/src/share/classes/java/net/URLPermission.java
index f6572cd..7ad56a1 100644
--- a/src/share/classes/java/net/URLPermission.java
+++ b/src/share/classes/java/net/URLPermission.java
@@ -45,7 +45,7 @@
* </pre>
* <i>scheme</i> will typically be http or https, but is not restricted by this
* class.
- * <i>authority</i> is specified as:<p>
+ * <i>authority</i> is specified as:
* <pre>
* authority = hostrange [ : portrange ]
* portrange = portnumber | -portnumber | portnumber-[portnumber] | *
@@ -223,7 +223,7 @@
* Checks if this URLPermission implies the given permission.
* Specifically, the following checks are done as if in the
* following sequence:
- * <p><ul>
+ * <ul>
* <li>if 'p' is not an instance of URLPermission return false</li>
* <li>if any of p's methods are not in this's method list, and if
* this's method list is not equal to "*", then return false.</li>
@@ -242,7 +242,7 @@
* <li>otherwise, return false</li>
* </ul>
* <p>Some examples of how paths are matched are shown below:
- * <p><table border>
+ * <table border>
* <caption>Examples of Path Matching</caption>
* <tr><th>this's path</th><th>p's path</th><th>match</th></tr>
* <tr><td>/a/b</td><td>/a/b</td><td>yes</td></tr>
@@ -353,7 +353,7 @@
return getActions().hashCode()
+ scheme.hashCode()
+ authority.hashCode()
- + path == null ? 0 : path.hashCode();
+ + (path == null ? 0 : path.hashCode());
}
diff --git a/src/share/classes/java/net/package-info.java b/src/share/classes/java/net/package-info.java
index 6552b30..fda2e4f 100644
--- a/src/share/classes/java/net/package-info.java
+++ b/src/share/classes/java/net/package-info.java
@@ -127,9 +127,9 @@
* resources, then convert it into a {@link java.net.URL} when it is time to
* access the resource. From that URL, you can either get the
* {@link java.net.URLConnection} for fine control, or get directly the
- * InputStream.<p>
+ * InputStream.
* <p>Here is an example:</p>
- * <p><pre>
+ * <pre>
* URI uri = new URI("http://java.sun.com/");
* URL url = uri.toURL();
* InputStream in = url.openStream();
@@ -147,7 +147,7 @@
* the {@code java.protocol.handler.pkgs} system property. For instance if
* it is set to {@code myapp.protocols}, then the URL code will try, in the
* case of http, first to load {@code myapp.protocols.http.Handler}, then,
- * if this fails, {@code http.Handler} from the default location.<p>
+ * if this fails, {@code http.Handler} from the default location.
* <p>Note that the Handler class <b>has to</b> be a subclass of the abstract
* class {@link java.net.URLStreamHandler}.</p>
* <h2>Additional Specification</h2>
diff --git a/src/share/classes/java/nio/X-Buffer.java.template b/src/share/classes/java/nio/X-Buffer.java.template
index 60f0733..acc8fc8 100644
--- a/src/share/classes/java/nio/X-Buffer.java.template
+++ b/src/share/classes/java/nio/X-Buffer.java.template
@@ -1129,7 +1129,7 @@
*
* <p> Two $type$ buffers are equal if, and only if,
*
- * <p><ol>
+ * <ol>
*
* <li><p> They have the same element type, </p></li>
*
diff --git a/src/share/classes/java/nio/file/FileSystem.java b/src/share/classes/java/nio/file/FileSystem.java
index 2296cad..2a961fb 100644
--- a/src/share/classes/java/nio/file/FileSystem.java
+++ b/src/share/classes/java/nio/file/FileSystem.java
@@ -355,7 +355,7 @@
*
* <p> The following rules are used to interpret glob patterns:
*
- * <p> <ul>
+ * <ul>
* <li><p> The {@code *} character matches zero or more {@link Character
* characters} of a {@link Path#getName(int) name} component without
* crossing directory boundaries. </p></li>
diff --git a/src/share/classes/java/rmi/RMISecurityManager.java b/src/share/classes/java/rmi/RMISecurityManager.java
index 3759e7f..b260c49 100644
--- a/src/share/classes/java/rmi/RMISecurityManager.java
+++ b/src/share/classes/java/rmi/RMISecurityManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -28,35 +28,38 @@
import java.security.*;
/**
- * A subclass of {@link SecurityManager} used by RMI applications that use
- * downloaded code. RMI's class loader will not download any classes from
- * remote locations if no security manager has been set.
- * <code>RMISecurityManager</code> does not apply to applets, which run
- * under the protection of their browser's security manager.
+ * {@code RMISecurityManager} implements a policy identical to the policy
+ * implemented by {@link SecurityManager}. RMI applications
+ * should use the {@code SecurityManager} class or another appropriate
+ * {@code SecurityManager} implementation instead of this class. RMI's class
+ * loader will download classes from remote locations only if a security
+ * manager has been set.
*
- * <code>RMISecurityManager</code> implements a policy that
- * is no different than the policy implemented by {@link SecurityManager}.
- * Therefore an RMI application should use the <code>SecurityManager</code>
- * class or another application-specific <code>SecurityManager</code>
- * implementation instead of this class.
+ * @implNote
+ * <p>Applets typically run in a container that already has a security
+ * manager, so there is generally no need for applets to set a security
+ * manager. If you have a standalone application, you might need to set a
+ * {@code SecurityManager} in order to enable class downloading. This can be
+ * done by adding the following to your code. (It needs to be executed before
+ * RMI can download code from remote hosts, so it most likely needs to appear
+ * in the {@code main} method of your application.)
*
- * <p>To use a <code>SecurityManager</code> in your application, add
- * the following statement to your code (it needs to be executed before RMI
- * can download code from remote hosts, so it most likely needs to appear
- * in the <code>main</code> method of your application):
- *
- * <pre>
- * System.setSecurityManager(new SecurityManager());
- * </pre>
+ * <pre>{@code
+ * if (System.getSecurityManager() == null) {
+ * System.setSecurityManager(new SecurityManager());
+ * }
+ * }</pre>
*
* @author Roger Riggs
* @author Peter Jones
* @since JDK1.1
- **/
+ * @deprecated Use {@link SecurityManager} instead.
+ */
+@Deprecated
public class RMISecurityManager extends SecurityManager {
/**
- * Constructs a new <code>RMISecurityManager</code>.
+ * Constructs a new {@code RMISecurityManager}.
* @since JDK1.1
*/
public RMISecurityManager() {
diff --git a/src/share/classes/java/rmi/activation/ActivationGroup.java b/src/share/classes/java/rmi/activation/ActivationGroup.java
index 49dffd1..bfa64ba 100644
--- a/src/share/classes/java/rmi/activation/ActivationGroup.java
+++ b/src/share/classes/java/rmi/activation/ActivationGroup.java
@@ -74,7 +74,7 @@
* <code>ActivationGroup</code> will override the system properties
* with the properties requested when its
* <code>ActivationGroupDesc</code> was created, and will set a
- * <code>java.rmi.RMISecurityManager</code> as the default system
+ * {@link SecurityManager} as the default system
* security manager. If your application requires specific properties
* to be set when objects are activated in the group, the application
* should create a special <code>Properties</code> object containing
@@ -84,7 +84,7 @@
* <code>ActivationDesc</code>s (before the default
* <code>ActivationGroupDesc</code> is created). If your application
* requires the use of a security manager other than
- * <code>java.rmi.RMISecurityManager</code>, in the
+ * {@link SecurityManager}, in the
* ActivativationGroupDescriptor properties list you can set
* <code>java.security.manager</code> property to the name of the security
* manager you would like to install.
@@ -154,21 +154,21 @@
* active). If the object does not call
* <code>Activatable.inactive</code> when it deactivates, the
* object will never be garbage collected since the group keeps
- * strong references to the objects it creates. <p>
+ * strong references to the objects it creates.
*
* <p>The group's <code>inactiveObject</code> method unexports the
* remote object from the RMI runtime so that the object can no
* longer receive incoming RMI calls. An object will only be unexported
* if the object has no pending or executing calls.
* The subclass of <code>ActivationGroup</code> must override this
- * method and unexport the object. <p>
+ * method and unexport the object.
*
* <p>After removing the object from the RMI runtime, the group
* must inform its <code>ActivationMonitor</code> (via the monitor's
* <code>inactiveObject</code> method) that the remote object is
* not currently active so that the remote object will be
* re-activated by the activator upon a subsequent activation
- * request.<p>
+ * request.
*
* <p>This method simply informs the group's monitor that the object
* is inactive. It is up to the concrete subclass of ActivationGroup
@@ -235,7 +235,7 @@
* <p>Note that if your application creates its own custom
* activation group, a security manager must be set for that
* group. Otherwise objects cannot be activated in the group.
- * <code>java.rmi.RMISecurityManager</code> is set by default.
+ * {@link SecurityManager} is set by default.
*
* <p>If a security manager is already set in the group VM, this
* method first calls the security manager's
diff --git a/src/share/classes/java/rmi/dgc/VMID.java b/src/share/classes/java/rmi/dgc/VMID.java
index 45e5859..913c598 100644
--- a/src/share/classes/java/rmi/dgc/VMID.java
+++ b/src/share/classes/java/rmi/dgc/VMID.java
@@ -67,7 +67,7 @@
* conditions: a) the conditions for uniqueness for objects of
* the class <code>java.rmi.server.UID</code> are satisfied, and b) an
* address can be obtained for this host that is unique and constant
- * for the lifetime of this object. <p>
+ * for the lifetime of this object.
*/
public VMID() {
addr = randomBytes;
diff --git a/src/share/classes/java/rmi/server/RMISocketFactory.java b/src/share/classes/java/rmi/server/RMISocketFactory.java
index ec9ade2..c9b8a47 100644
--- a/src/share/classes/java/rmi/server/RMISocketFactory.java
+++ b/src/share/classes/java/rmi/server/RMISocketFactory.java
@@ -41,7 +41,15 @@
* (due to a firewall), the runtime uses HTTP with the explicit port
* number of the server. If the firewall does not allow this type of
* communication, then HTTP to a cgi-bin script on the server is used
- * to POST the RMI call.
+ * to POST the RMI call. The HTTP tunneling mechanisms are disabled by
+ * default. This behavior is controlled by the {@code java.rmi.server.disableHttp}
+ * property, whose default value is {@code true}. Setting this property's
+ * value to {@code false} will enable the HTTP tunneling mechanisms.
+ *
+ * <p><strong>Deprecated: HTTP Tunneling.</strong> <em>The HTTP tunneling mechanisms
+ * described above, specifically HTTP with an explicit port and HTTP to a
+ * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are
+ * subject to removal in a future release of the platform.</em>
*
* <p>The default socket factory implementation creates server sockets that
* are bound to the wildcard address, which accepts requests from all network
diff --git a/src/share/classes/java/rmi/server/RemoteStub.java b/src/share/classes/java/rmi/server/RemoteStub.java
index 988132c..36f8eb0 100644
--- a/src/share/classes/java/rmi/server/RemoteStub.java
+++ b/src/share/classes/java/rmi/server/RemoteStub.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,7 +25,8 @@
package java.rmi.server;
/**
- * The <code>RemoteStub</code> class is the common superclass to client
+ * The {@code RemoteStub} class is the common superclass of
+ * statically generated client
* stubs and provides the framework to support a wide range of remote
* reference semantics. Stub objects are surrogates that support
* exactly the same set of remote interfaces defined by the actual
@@ -33,21 +34,26 @@
*
* @author Ann Wollrath
* @since JDK1.1
+ *
+ * @deprecated Statically generated stubs are deprecated, since
+ * stubs are generated dynamically. See {@link UnicastRemoteObject}
+ * for information about dynamic stub generation.
*/
+@Deprecated
abstract public class RemoteStub extends RemoteObject {
/** indicate compatibility with JDK 1.1.x version of class */
private static final long serialVersionUID = -1585587260594494182L;
/**
- * Constructs a <code>RemoteStub</code>.
+ * Constructs a {@code RemoteStub}.
*/
protected RemoteStub() {
super();
}
/**
- * Constructs a <code>RemoteStub</code>, with the specified remote
+ * Constructs a {@code RemoteStub} with the specified remote
* reference.
*
* @param ref the remote reference
@@ -58,14 +64,17 @@
}
/**
- * Sets the remote reference inside the remote stub.
+ * Throws {@link UnsupportedOperationException}.
*
* @param stub the remote stub
* @param ref the remote reference
+ * @throws UnsupportedOperationException always
* @since JDK1.1
- * @deprecated no replacement. The <code>setRef</code> method
- * is not needed since <code>RemoteStub</code>s can be created with
- * the <code>RemoteStub(RemoteRef)</code> constructor.
+ * @deprecated No replacement. The {@code setRef} method
+ * was intended for setting the remote reference of a remote
+ * stub. This is unnecessary, since {@code RemoteStub}s can be created
+ * and initialized with a remote reference through use of
+ * the {@link #RemoteStub(RemoteRef)} constructor.
*/
@Deprecated
protected static void setRef(RemoteStub stub, RemoteRef ref) {
diff --git a/src/share/classes/java/rmi/server/ServerRef.java b/src/share/classes/java/rmi/server/ServerRef.java
index cf73b7c..f0b521e 100644
--- a/src/share/classes/java/rmi/server/ServerRef.java
+++ b/src/share/classes/java/rmi/server/ServerRef.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -33,7 +33,9 @@
*
* @author Ann Wollrath
* @since JDK1.1
+ * @deprecated No replacement. This interface is unused and is obsolete.
*/
+@Deprecated
public interface ServerRef extends RemoteRef {
/** indicate compatibility with JDK 1.1.x version of class. */
diff --git a/src/share/classes/java/rmi/server/SocketSecurityException.java b/src/share/classes/java/rmi/server/SocketSecurityException.java
index 61fc915..3fbec26 100644
--- a/src/share/classes/java/rmi/server/SocketSecurityException.java
+++ b/src/share/classes/java/rmi/server/SocketSecurityException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -30,7 +30,9 @@
*
* @author Ann Wollrath
* @since JDK1.1
- **/
+ * @deprecated This class is obsolete. Use {@link ExportException} instead.
+ */
+@Deprecated
public class SocketSecurityException extends ExportException {
/* indicate compatibility with JDK 1.1.x version of class */
diff --git a/src/share/classes/java/rmi/server/UnicastRemoteObject.java b/src/share/classes/java/rmi/server/UnicastRemoteObject.java
index be86c27..802d714 100644
--- a/src/share/classes/java/rmi/server/UnicastRemoteObject.java
+++ b/src/share/classes/java/rmi/server/UnicastRemoteObject.java
@@ -30,52 +30,88 @@
/**
* Used for exporting a remote object with JRMP and obtaining a stub
- * that communicates to the remote object.
+ * that communicates to the remote object. Stubs are either generated
+ * at runtime using dynamic proxy objects, or they are generated statically
+ * at build time, typically using the {@code rmic} tool.
*
- * <p>For the constructors and static <code>exportObject</code> methods
- * below, the stub for a remote object being exported is obtained as
- * follows:
+ * <p><strong>Deprecated: Static Stubs.</strong> <em>Support for statically
+ * generated stubs is deprecated. This includes the API in this class that
+ * requires the use of static stubs, as well as the runtime support for
+ * loading static stubs. Generating stubs dynamically is preferred, using one
+ * of the five non-deprecated ways of exporting objects as listed below. Do
+ * not run {@code rmic} to generate static stub classes. It is unnecessary, and
+ * it is also deprecated.</em>
*
- * <p><ul>
+ * <p>There are six ways to export remote objects:
*
- * <li>If the remote object is exported using the {@link
- * #exportObject(Remote) UnicastRemoteObject.exportObject(Remote)} method,
- * a stub class (typically pregenerated from the remote object's class
- * using the <code>rmic</code> tool) is loaded and an instance of that stub
- * class is constructed as follows.
+ * <ol>
+ *
+ * <li>Subclassing {@code UnicastRemoteObject} and calling the
+ * {@link #UnicastRemoteObject()} constructor.
+ *
+ * <li>Subclassing {@code UnicastRemoteObject} and calling the
+ * {@link #UnicastRemoteObject(int) UnicastRemoteObject(port)} constructor.
+ *
+ * <li>Subclassing {@code UnicastRemoteObject} and calling the
+ * {@link #UnicastRemoteObject(int, RMIClientSocketFactory, RMIServerSocketFactory)
+ * UnicastRemoteObject(port, csf, ssf)} constructor.
+ *
+ * <li>Calling the
+ * {@link #exportObject(Remote) exportObject(Remote)} method.
+ * <strong>Deprecated.</strong>
+ *
+ * <li>Calling the
+ * {@link #exportObject(Remote, int) exportObject(Remote, port)} method.
+ *
+ * <li>Calling the
+ * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory)
+ * exportObject(Remote, port, csf, ssf)} method.
+ *
+ * </ol>
+ *
+ * <p>The fourth technique, {@link #exportObject(Remote)},
+ * always uses statically generated stubs and is deprecated.
+ *
+ * <p>The other five techniques all use the following approach: if the
+ * {@code java.rmi.server.ignoreStubClasses} property is {@code true}
+ * (case insensitive) or if a static stub cannot be found, stubs are generated
+ * dynamically using {@link java.lang.reflect.Proxy Proxy} objects. Otherwise,
+ * static stubs are used.
+ *
+ * <p>The default value of the
+ * {@code java.rmi.server.ignoreStubClasses} property is {@code false}.
+ *
+ * <p>Statically generated stubs are typically pregenerated from the
+ * remote object's class using the {@code rmic} tool. A static stub is
+ * loaded and an instance of that stub class is constructed as described
+ * below.
+ *
* <ul>
*
- * <li>A "root class" is determined as follows: if the remote object's
+ * <li>A "root class" is determined as follows: if the remote object's
* class directly implements an interface that extends {@link Remote}, then
* the remote object's class is the root class; otherwise, the root class is
* the most derived superclass of the remote object's class that directly
- * implements an interface that extends <code>Remote</code>.
+ * implements an interface that extends {@code Remote}.
*
* <li>The name of the stub class to load is determined by concatenating
- * the binary name of the root class with the suffix <code>"_Stub"</code>.
+ * the binary name of the root class with the suffix {@code _Stub}.
*
* <li>The stub class is loaded by name using the class loader of the root
- * class. The stub class must extend {@link RemoteStub} and must have a
- * public constructor that has one parameter, of type {@link RemoteRef}.
+ * class. The stub class must extend {@link RemoteStub} and must have a
+ * public constructor that has one parameter of type {@link RemoteRef}.
*
* <li>Finally, an instance of the stub class is constructed with a
* {@link RemoteRef}.
- * </ul>
*
- * <li>If the appropriate stub class could not be found, or the stub class
- * could not be loaded, or a problem occurs creating the stub instance, a
+ * <li>If the appropriate stub class could not be found, or if the stub class
+ * could not be loaded, or if a problem occurs creating the stub instance, a
* {@link StubNotFoundException} is thrown.
*
- * <p>
- * <li>For all other means of exporting:
- * <p><ul>
+ * </ul>
*
- * <li>If the remote object's stub class (as defined above) could not be
- * loaded or the system property
- * <code>java.rmi.server.ignoreStubClasses</code> is set to
- * <code>"true"</code> (case insensitive), a {@link
- * java.lang.reflect.Proxy} instance is constructed with the following
- * properties:
+ * <p>Stubs are dynamically generated by constructing an instance of
+ * a {@link java.lang.reflect.Proxy Proxy} with the following characteristics:
*
* <ul>
*
@@ -91,29 +127,13 @@
*
* <li>If the proxy could not be created, a {@link StubNotFoundException}
* will be thrown.
- * </ul>
- *
- * <p>
- * <li>Otherwise, an instance of the remote object's stub class (as
- * described above) is used as the stub.
*
* </ul>
- * </ul>
- *
- * <p>If an object is exported with the
- * {@link #exportObject(Remote) exportObject(Remote)}
- * or
- * {@link #exportObject(Remote, int) exportObject(Remote, port)}
- * methods, or if a subclass constructor invokes one of the
- * {@link #UnicastRemoteObject()}
- * or
- * {@link #UnicastRemoteObject(int) UnicastRemoteObject(port)}
- * constructors, the object is exported with a server socket created using the
- * {@link RMISocketFactory}
- * class.
*
* @implNote
- * <p>By default, server sockets created by the {@link RMISocketFactory} class
+ * Depending upon which constructor or static method is used for exporting an
+ * object, {@link RMISocketFactory} may be used for creating sockets.
+ * By default, server sockets created by {@link RMISocketFactory}
* listen on all network interfaces. See the
* {@link RMISocketFactory} class and the section
* <a href="{@docRoot}/../platform/rmi/spec/rmi-server29.html">RMI Socket Factories</a>
@@ -148,6 +168,10 @@
/**
* Creates and exports a new UnicastRemoteObject object using an
* anonymous port.
+ *
+ * <p>The object is exported with a server socket
+ * created using the {@link RMISocketFactory} class.
+ *
* @throws RemoteException if failed to export object
* @since JDK1.1
*/
@@ -159,6 +183,10 @@
/**
* Creates and exports a new UnicastRemoteObject object using the
* particular supplied port.
+ *
+ * <p>The object is exported with a server socket
+ * created using the {@link RMISocketFactory} class.
+ *
* @param port the port number on which the remote object receives calls
* (if <code>port</code> is zero, an anonymous port is chosen)
* @throws RemoteException if failed to export object
@@ -173,6 +201,11 @@
/**
* Creates and exports a new UnicastRemoteObject object using the
* particular supplied port and socket factories.
+ *
+ * <p>Either socket factory may be {@code null}, in which case
+ * the corresponding client or server socket creation method of
+ * {@link RMISocketFactory} is used instead.
+ *
* @param port the port number on which the remote object receives calls
* (if <code>port</code> is zero, an anonymous port is chosen)
* @param csf the client-side socket factory for making calls to the
@@ -238,12 +271,23 @@
/**
* Exports the remote object to make it available to receive incoming
- * calls using an anonymous port.
+ * calls using an anonymous port. This method will always return a
+ * statically generated stub.
+ *
+ * <p>The object is exported with a server socket
+ * created using the {@link RMISocketFactory} class.
+ *
* @param obj the remote object to be exported
* @return remote object stub
* @exception RemoteException if export fails
* @since JDK1.1
+ * @deprecated This method is deprecated because it supports only static stubs.
+ * Use {@link #exportObject(Remote, int) exportObject(Remote, port)} or
+ * {@link #exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory)
+ * exportObject(Remote, port, csf, ssf)}
+ * instead.
*/
+ @Deprecated
public static RemoteStub exportObject(Remote obj)
throws RemoteException
{
@@ -260,6 +304,10 @@
/**
* Exports the remote object to make it available to receive incoming
* calls, using the particular supplied port.
+ *
+ * <p>The object is exported with a server socket
+ * created using the {@link RMISocketFactory} class.
+ *
* @param obj the remote object to be exported
* @param port the port to export the object on
* @return remote object stub
@@ -275,6 +323,11 @@
/**
* Exports the remote object to make it available to receive incoming
* calls, using a transport specified by the given socket factory.
+ *
+ * <p>Either socket factory may be {@code null}, in which case
+ * the corresponding client or server socket creation method of
+ * {@link RMISocketFactory} is used instead.
+ *
* @param obj the remote object to be exported
* @param port the port to export the object on
* @param csf the client-side socket factory for making calls to the
diff --git a/src/share/classes/java/rmi/server/package.html b/src/share/classes/java/rmi/server/package.html
index 290ca9a..1bfa46d 100644
--- a/src/share/classes/java/rmi/server/package.html
+++ b/src/share/classes/java/rmi/server/package.html
@@ -1,5 +1,5 @@
<!--
- Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 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
@@ -32,6 +32,27 @@
generated by the rmic stub compiler. Another group of classes
implements the RMI Transport protocol and HTTP tunneling.
+<p><strong>Deprecated: HTTP Tunneling.</strong> <em>The HTTP tunneling
+mechanism has been deprecated. See {@link java.rmi.server.RMISocketFactory} for
+further information.</em>
+
+<p><strong>Deprecated: Skeletons and Static Stubs.</strong>
+
+<em>Skeletons and statically generated stubs are deprecated. This
+includes the APIs in this package that require the use of skeletons
+or static stubs, the runtime support for them, and the use of the
+{@code rmic} stub compiler to generate them. Support for skeletons
+and static stubs may be removed in a future release of the
+platform. Skeletons are unnecessary, as server-side method dispatching
+is handled directly by the RMI runtime. Statically generated stubs are
+unnecessary, as stubs are generated dynamically using {@link
+java.lang.reflect.Proxy Proxy} objects. See {@link
+java.rmi.server.UnicastRemoteObject UnicastRemoteObject} for
+information about dynamic stub generation. Generation of skeletons and
+static stubs was typically performed as part of an application's build
+process by calling the {@code rmic} tool. This is unnecessary, and
+calls to {@code rmic} can simply be omitted.</em>
+
<!--
<h2>Package Specification</h2>
diff --git a/src/share/classes/java/security/AccessControlContext.java b/src/share/classes/java/security/AccessControlContext.java
index 9b5bc07..1805aaf 100644
--- a/src/share/classes/java/security/AccessControlContext.java
+++ b/src/share/classes/java/security/AccessControlContext.java
@@ -350,6 +350,10 @@
return combiner;
}
+ boolean isAuthorized() {
+ return isAuthorized;
+ }
+
/**
* Determines whether the access request indicated by the
* specified permission should be allowed or denied, based on
diff --git a/src/share/classes/java/security/AccessController.java b/src/share/classes/java/security/AccessController.java
index a7d0899..36408a8 100644
--- a/src/share/classes/java/security/AccessController.java
+++ b/src/share/classes/java/security/AccessController.java
@@ -39,9 +39,9 @@
* <ul>
* <li> to decide whether an access to a critical system
* resource is to be allowed or denied, based on the security policy
- * currently in effect,<p>
+ * currently in effect,
* <li>to mark code as being "privileged", thus affecting subsequent
- * access determinations, and<p>
+ * access determinations, and
* <li>to obtain a "snapshot" of the current calling context so
* access-control decisions from a different context can be made with
* respect to the saved context. </ul>
@@ -344,9 +344,10 @@
* If the action's {@code run} method throws an (unchecked) exception,
* it will propagate through this method.
* <p>
- * If a security manager is installed and the {@code AccessControlContext}
- * was not created by system code and the caller's {@code ProtectionDomain}
- * has not been granted the {@literal "createAccessControlContext"}
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
* {@link java.security.SecurityPermission}, then the action is performed
* with no permissions.
*
@@ -384,6 +385,13 @@
* <p>
* If the action's {@code run} method throws an (unchecked) exception,
* it will propagate through this method.
+ * <p>
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
+ * {@link java.security.SecurityPermission}, then the action is performed
+ * with no permissions.
*
* @param <T> the type of the value returned by the PrivilegedAction's
* {@code run} method.
@@ -438,6 +446,13 @@
*
* <p> This method preserves the current AccessControlContext's
* DomainCombiner (which may be null) while the action is performed.
+ * <p>
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
+ * {@link java.security.SecurityPermission}, then the action is performed
+ * with no permissions.
*
* @param <T> the type of the value returned by the PrivilegedAction's
* {@code run} method.
@@ -571,8 +586,18 @@
AccessControlContext parent, AccessControlContext context,
Permission[] perms)
{
- return new AccessControlContext(getCallerPD(caller), combiner, parent,
- context, perms);
+ ProtectionDomain callerPD = getCallerPD(caller);
+ // check if caller is authorized to create context
+ if (context != null && !context.isAuthorized() &&
+ System.getSecurityManager() != null &&
+ !callerPD.impliesCreateAccessControlContext())
+ {
+ ProtectionDomain nullPD = new ProtectionDomain(null, null);
+ return new AccessControlContext(new ProtectionDomain[] { nullPD });
+ } else {
+ return new AccessControlContext(callerPD, combiner, parent,
+ context, perms);
+ }
}
private static ProtectionDomain getCallerPD(final Class <?> caller) {
@@ -597,9 +622,10 @@
* If the action's {@code run} method throws an <i>unchecked</i>
* exception, it will propagate through this method.
* <p>
- * If a security manager is installed and the {@code AccessControlContext}
- * was not created by system code and the caller's {@code ProtectionDomain}
- * has not been granted the {@literal "createAccessControlContext"}
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
* {@link java.security.SecurityPermission}, then the action is performed
* with no permissions.
*
@@ -641,6 +667,13 @@
* <p>
* If the action's {@code run} method throws an (unchecked) exception,
* it will propagate through this method.
+ * <p>
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
+ * {@link java.security.SecurityPermission}, then the action is performed
+ * with no permissions.
*
* @param <T> the type of the value returned by the
* PrivilegedExceptionAction's {@code run} method.
@@ -697,6 +730,13 @@
*
* <p> This method preserves the current AccessControlContext's
* DomainCombiner (which may be null) while the action is performed.
+ * <p>
+ * If a security manager is installed and the specified
+ * {@code AccessControlContext} was not created by system code and the
+ * caller's {@code ProtectionDomain} has not been granted the
+ * {@literal "createAccessControlContext"}
+ * {@link java.security.SecurityPermission}, then the action is performed
+ * with no permissions.
*
* @param <T> the type of the value returned by the
* PrivilegedExceptionAction's {@code run} method.
diff --git a/src/share/classes/java/security/AlgorithmParameterGenerator.java b/src/share/classes/java/security/AlgorithmParameterGenerator.java
index 307aaaf..7f9c7cb 100644
--- a/src/share/classes/java/security/AlgorithmParameterGenerator.java
+++ b/src/share/classes/java/security/AlgorithmParameterGenerator.java
@@ -48,7 +48,7 @@
* of the prime modulus (in bits).
* When using this approach, algorithm-specific parameter generation
* values - if any - default to some standard values, unless they can be
- * derived from the specified size.<P>
+ * derived from the specified size.
*
* <li>The other approach initializes a parameter generator object
* using algorithm-specific semantics, which are represented by a set of
diff --git a/src/share/classes/java/security/BasicPermission.java b/src/share/classes/java/security/BasicPermission.java
index 2d0c966..89cc2f9 100644
--- a/src/share/classes/java/security/BasicPermission.java
+++ b/src/share/classes/java/security/BasicPermission.java
@@ -57,7 +57,6 @@
* Subclasses may implement actions on top of BasicPermission,
* if desired.
* <p>
- * <P>
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
@@ -153,9 +152,9 @@
* Checks if the specified permission is "implied" by
* this object.
* <P>
- * More specifically, this method returns true if:<p>
+ * More specifically, this method returns true if:
* <ul>
- * <li> <i>p</i>'s class is the same as this object's class, and<p>
+ * <li> <i>p</i>'s class is the same as this object's class, and
* <li> <i>p</i>'s name equals or (in the case of wildcards)
* is implied by this object's
* name. For example, "a.b.*" implies "a.b.c".
diff --git a/src/share/classes/java/security/CodeSource.java b/src/share/classes/java/security/CodeSource.java
index b6167cb..62a5959 100644
--- a/src/share/classes/java/security/CodeSource.java
+++ b/src/share/classes/java/security/CodeSource.java
@@ -234,7 +234,7 @@
* Returns true if this CodeSource object "implies" the specified CodeSource.
* <p>
* More specifically, this method makes the following checks.
- * If any fail, it returns false. If they all succeed, it returns true.<p>
+ * If any fail, it returns false. If they all succeed, it returns true.
* <ul>
* <li> <i>codesource</i> must not be null.
* <li> If this object's certificates are not null, then all
@@ -242,7 +242,7 @@
* certificates.
* <li> If this object's location (getLocation()) is not null, then the
* following checks are made against this object's location and
- * <i>codesource</i>'s:<p>
+ * <i>codesource</i>'s:
* <ul>
* <li> <i>codesource</i>'s location must not be null.
*
diff --git a/src/share/classes/java/security/Key.java b/src/share/classes/java/security/Key.java
index 0ae4e38..c0c63d7 100644
--- a/src/share/classes/java/security/Key.java
+++ b/src/share/classes/java/security/Key.java
@@ -39,7 +39,7 @@
* RSA), which will work with those algorithms and with related
* algorithms (such as MD5 with RSA, SHA-1 with RSA, Raw DSA, etc.)
* The name of the algorithm of a key is obtained using the
- * {@link #getAlgorithm() getAlgorithm} method.<P>
+ * {@link #getAlgorithm() getAlgorithm} method.
*
* <LI>An Encoded Form
*
@@ -65,12 +65,11 @@
* For more information, see
* <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
* Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>.
- * <P>
*
* <LI>A Format
*
* <P>This is the name of the format of the encoded key. It is returned
- * by the {@link #getFormat() getFormat} method.<P>
+ * by the {@link #getFormat() getFormat} method.
*
* </UL>
*
diff --git a/src/share/classes/java/security/KeyPairGenerator.java b/src/share/classes/java/security/KeyPairGenerator.java
index 78b100c..c09d251 100644
--- a/src/share/classes/java/security/KeyPairGenerator.java
+++ b/src/share/classes/java/security/KeyPairGenerator.java
@@ -77,7 +77,6 @@
* providers might have precomputed parameter sets for more than just the
* three modulus sizes mentioned above. Still others might not have a list of
* precomputed parameters at all and instead always create new parameter sets.
- * <p>
*
* <li><b>Algorithm-Specific Initialization</b>
* <p>For situations where a set of algorithm-specific parameters already
diff --git a/src/share/classes/java/security/KeyStore.java b/src/share/classes/java/security/KeyStore.java
index f770d97..80bf17d 100644
--- a/src/share/classes/java/security/KeyStore.java
+++ b/src/share/classes/java/security/KeyStore.java
@@ -98,7 +98,6 @@
* KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
* </pre>
* The system will return a keystore implementation for the default type.
- * <p>
*
* <li>To provide a specific keystore type:
* <pre>
diff --git a/src/share/classes/java/security/MessageDigest.java b/src/share/classes/java/security/MessageDigest.java
index fa68678..60d41ff 100644
--- a/src/share/classes/java/security/MessageDigest.java
+++ b/src/share/classes/java/security/MessageDigest.java
@@ -54,21 +54,21 @@
*
* <p>Implementations are free to implement the Cloneable interface.
* Client applications can test cloneability by attempting cloning
- * and catching the CloneNotSupportedException: <p>
+ * and catching the CloneNotSupportedException:
*
-* <pre>
-* MessageDigest md = MessageDigest.getInstance("SHA");
-*
-* try {
-* md.update(toChapter1);
-* MessageDigest tc1 = md.clone();
-* byte[] toChapter1Digest = tc1.digest();
-* md.update(toChapter2);
-* ...etc.
-* } catch (CloneNotSupportedException cnse) {
-* throw new DigestException("couldn't make digest of partial content");
-* }
-* </pre>
+ * <pre>{@code
+ * MessageDigest md = MessageDigest.getInstance("SHA");
+ *
+ * try {
+ * md.update(toChapter1);
+ * MessageDigest tc1 = md.clone();
+ * byte[] toChapter1Digest = tc1.digest();
+ * md.update(toChapter2);
+ * ...etc.
+ * } catch (CloneNotSupportedException cnse) {
+ * throw new DigestException("couldn't make digest of partial content");
+ * }
+ * }</pre>
*
* <p>Note that if a given implementation is not cloneable, it is
* still possible to compute intermediate digests by instantiating
diff --git a/src/share/classes/java/security/Permission.java b/src/share/classes/java/security/Permission.java
index dfa7163..088f97c 100644
--- a/src/share/classes/java/security/Permission.java
+++ b/src/share/classes/java/security/Permission.java
@@ -138,14 +138,14 @@
* Returns the hash code value for this Permission object.
* <P>
* The required {@code hashCode} behavior for Permission Objects is
- * the following: <p>
+ * the following:
* <ul>
* <li>Whenever it is invoked on the same Permission object more than
* once during an execution of a Java application, the
* {@code hashCode} method
* must consistently return the same integer. This integer need not
* remain consistent from one execution of an application to another
- * execution of the same application. <p>
+ * execution of the same application.
* <li>If two Permission objects are equal according to the
* {@code equals}
* method, then calling the {@code hashCode} method on each of the
diff --git a/src/share/classes/java/security/PermissionCollection.java b/src/share/classes/java/security/PermissionCollection.java
index 58b7bdf..3f13b9f 100644
--- a/src/share/classes/java/security/PermissionCollection.java
+++ b/src/share/classes/java/security/PermissionCollection.java
@@ -37,7 +37,6 @@
* collection, using the {@code implies} method.
* <LI> enumerate all the permissions, using the {@code elements} method.
* </UL>
- * <P>
*
* <p>When it is desirable to group together a number of Permission objects
* of the same type, the {@code newPermissionCollection} method on that
diff --git a/src/share/classes/java/security/Provider.java b/src/share/classes/java/security/Provider.java
index 89a7b49..0d5309c 100644
--- a/src/share/classes/java/security/Provider.java
+++ b/src/share/classes/java/security/Provider.java
@@ -30,6 +30,9 @@
import static java.util.Locale.ENGLISH;
import java.lang.ref.*;
import java.lang.reflect.*;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
/**
* This class represents a "provider" for the
@@ -185,15 +188,10 @@
* Clears this provider so that it no longer contains the properties
* used to look up facilities implemented by the provider.
*
- * <p>First, if there is a security manager, its
- * {@code checkSecurityAccess} method is called with the string
- * {@code "clearProviderProperties."+name} (where {@code name}
- * is the provider name) to see if it's ok to clear this provider.
- * If the default implementation of {@code checkSecurityAccess}
- * is used (that is, that method is not overriden), then this results in
- * a call to the security manager's {@code checkPermission} method
- * with a {@code SecurityPermission("clearProviderProperties."+name)}
- * permission.
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "clearProviderProperties."+name}
+ * (where {@code name} is the provider name) to see if it's ok to clear
+ * this provider.
*
* @throws SecurityException
* if a security manager exists and its {@link
@@ -202,6 +200,7 @@
*
* @since 1.2
*/
+ @Override
public synchronized void clear() {
check("clearProviderProperties."+name);
if (debug != null) {
@@ -218,6 +217,7 @@
* input stream.
* @see java.util.Properties#load
*/
+ @Override
public synchronized void load(InputStream inStream) throws IOException {
check("putProviderProperty."+name);
if (debug != null) {
@@ -235,6 +235,7 @@
*
* @since 1.2
*/
+ @Override
public synchronized void putAll(Map<?,?> t) {
check("putProviderProperty."+name);
if (debug != null) {
@@ -250,6 +251,7 @@
* @see java.util.Map.Entry
* @since 1.2
*/
+ @Override
public synchronized Set<Map.Entry<Object,Object>> entrySet() {
checkInitialized();
if (entrySet == null) {
@@ -276,6 +278,7 @@
*
* @since 1.2
*/
+ @Override
public Set<Object> keySet() {
checkInitialized();
return Collections.unmodifiableSet(super.keySet());
@@ -287,6 +290,7 @@
*
* @since 1.2
*/
+ @Override
public Collection<Object> values() {
checkInitialized();
return Collections.unmodifiableCollection(super.values());
@@ -296,22 +300,10 @@
* Sets the {@code key} property to have the specified
* {@code value}.
*
- * <p>First, if there is a security manager, its
- * {@code checkSecurityAccess} method is called with the string
- * {@code "putProviderProperty."+name}, where {@code name} is the
- * provider name, to see if it's ok to set this provider's property values.
- * If the default implementation of {@code checkSecurityAccess}
- * is used (that is, that method is not overriden), then this results in
- * a call to the security manager's {@code checkPermission} method
- * with a {@code SecurityPermission("putProviderProperty."+name)}
- * permission.
- *
- * @param key the property key.
- *
- * @param value the property value.
- *
- * @return the previous value of the specified property
- * ({@code key}), or null if it did not have one.
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
*
* @throws SecurityException
* if a security manager exists and its {@link
@@ -320,6 +312,7 @@
*
* @since 1.2
*/
+ @Override
public synchronized Object put(Object key, Object value) {
check("putProviderProperty."+name);
if (debug != null) {
@@ -330,24 +323,38 @@
}
/**
+ * If the specified key is not already associated with a value (or is mapped
+ * to {@code null}) associates it with the given value and returns
+ * {@code null}, else returns the current value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ */
+ @Override
+ public synchronized Object putIfAbsent(Object key, Object value) {
+ check("putProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Set " + name + " provider property [" +
+ key + "/" + value +"]");
+ }
+ return implPutIfAbsent(key, value);
+ }
+
+ /**
* Removes the {@code key} property (and its corresponding
* {@code value}).
*
- * <p>First, if there is a security manager, its
- * {@code checkSecurityAccess} method is called with the string
- * {@code "removeProviderProperty."+name}, where {@code name} is
- * the provider name, to see if it's ok to remove this provider's
- * properties. If the default implementation of
- * {@code checkSecurityAccess} is used (that is, that method is not
- * overriden), then this results in a call to the security manager's
- * {@code checkPermission} method with a
- * {@code SecurityPermission("removeProviderProperty."+name)}
- * permission.
- *
- * @param key the key for the property to be removed.
- *
- * @return the value to which the key had been mapped,
- * or null if the key did not have a mapping.
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "removeProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to remove this
+ * provider's properties.
*
* @throws SecurityException
* if a security manager exists and its {@link
@@ -356,6 +363,7 @@
*
* @since 1.2
*/
+ @Override
public synchronized Object remove(Object key) {
check("removeProviderProperty."+name);
if (debug != null) {
@@ -364,19 +372,245 @@
return implRemove(key);
}
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "removeProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to remove this
+ * provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to remove this provider's properties.
+ */
+ @Override
+ public synchronized boolean remove(Object key, Object value) {
+ check("removeProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Remove " + name + " provider property " + key);
+ }
+ return implRemove(key, value);
+ }
+
+ /**
+ * Replaces the entry for the specified key only if currently
+ * mapped to the specified value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ */
+ @Override
+ public synchronized boolean replace(Object key, Object oldValue,
+ Object newValue) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("Replace " + name + " provider property " + key);
+ }
+ return implReplace(key, oldValue, newValue);
+ }
+
+ /**
+ * Replaces the entry for the specified key only if it is
+ * currently mapped to some value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ */
+ @Override
+ public synchronized Object replace(Object key, Object value) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("Replace " + name + " provider property " + key);
+ }
+ return implReplace(key, value);
+ }
+
+ /**
+ * Replaces each entry's value with the result of invoking the given
+ * function on that entry, in the order entries are returned by an entry
+ * set iterator, until all entries have been processed or the function
+ * throws an exception.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ */
+ @Override
+ public synchronized void replaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("ReplaceAll " + name + " provider property ");
+ }
+ implReplaceAll(function);
+ }
+
+ /**
+ * Attempts to compute a mapping for the specified key and its
+ * current mapped value (or {@code null} if there is no current
+ * mapping).
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ */
+ @Override
+ public synchronized Object compute(Object key,
+ BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("Compute " + name + " provider property " + key);
+ }
+ return implCompute(key, remappingFunction);
+ }
+
+ /**
+ * If the specified key is not already associated with a value (or
+ * is mapped to {@code null}), attempts to compute its value using
+ * the given mapping function and enters it into this map unless
+ * {@code null}.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values and remove properties.
+ */
+ @Override
+ public synchronized Object computeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("ComputeIfAbsent " + name + " provider property " +
+ key);
+ }
+ return implComputeIfAbsent(key, mappingFunction);
+ }
+
+ /**
+ * If the value for the specified key is present and non-null, attempts to
+ * compute a new mapping given the key and its current mapped value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ */
+ @Override
+ public synchronized Object computeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("ComputeIfPresent " + name + " provider property " +
+ key);
+ }
+ return implComputeIfPresent(key, remappingFunction);
+ }
+
+ /**
+ * If the specified key is not already associated with a value or is
+ * associated with null, associates it with the given value. Otherwise,
+ * replaces the value with the results of the given remapping function,
+ * or removes if the result is null. This method may be of use when
+ * combining multiple mapped values for a key.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ */
+ @Override
+ public synchronized Object merge(Object key, Object value, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("Merge " + name + " provider property " + key);
+ }
+ return implMerge(key, value, remappingFunction);
+ }
+
// let javadoc show doc from superclass
+ @Override
public Object get(Object key) {
checkInitialized();
return super.get(key);
}
+ @Override
+ public synchronized Object getOrDefault(Object key, Object defaultValue) {
+ checkInitialized();
+ return super.getOrDefault(key, defaultValue);
+ }
+
+ @Override
+ public synchronized void forEach(BiConsumer<? super Object, ? super Object> action) {
+ checkInitialized();
+ super.forEach(action);
+ }
+
// let javadoc show doc from superclass
+ @Override
public Enumeration<Object> keys() {
checkInitialized();
return super.keys();
}
// let javadoc show doc from superclass
+ @Override
public Enumeration<Object> elements() {
checkInitialized();
return super.elements();
@@ -446,6 +680,19 @@
putAll(copy);
}
+ private boolean checkLegacy(Object key) {
+ String keyString = (String)key;
+ if (keyString.startsWith("Provider.")) {
+ return false;
+ }
+
+ legacyChanged = true;
+ if (legacyStrings == null) {
+ legacyStrings = new LinkedHashMap<String,String>();
+ }
+ return true;
+ }
+
/**
* Copies all of the mappings from the specified Map to this provider.
* Internal method to be called AFTER the security check has been
@@ -459,34 +706,121 @@
private Object implRemove(Object key) {
if (key instanceof String) {
- String keyString = (String)key;
- if (keyString.startsWith("Provider.")) {
+ if (!checkLegacy(key)) {
return null;
}
- legacyChanged = true;
- if (legacyStrings == null) {
- legacyStrings = new LinkedHashMap<String,String>();
- }
- legacyStrings.remove(keyString);
+ legacyStrings.remove((String)key);
}
return super.remove(key);
}
- private Object implPut(Object key, Object value) {
+ private boolean implRemove(Object key, Object value) {
+ if (key instanceof String && value instanceof String) {
+ if (!checkLegacy(key)) {
+ return false;
+ }
+ legacyStrings.remove((String)key, value);
+ }
+ return super.remove(key, value);
+ }
+
+ private boolean implReplace(Object key, Object oldValue, Object newValue) {
+ if ((key instanceof String) && (oldValue instanceof String) &&
+ (newValue instanceof String)) {
+ if (!checkLegacy(key)) {
+ return false;
+ }
+ legacyStrings.replace((String)key, (String)oldValue,
+ (String)newValue);
+ }
+ return super.replace(key, oldValue, newValue);
+ }
+
+ private Object implReplace(Object key, Object value) {
if ((key instanceof String) && (value instanceof String)) {
- String keyString = (String)key;
- if (keyString.startsWith("Provider.")) {
+ if (!checkLegacy(key)) {
return null;
}
- legacyChanged = true;
- if (legacyStrings == null) {
- legacyStrings = new LinkedHashMap<String,String>();
+ legacyStrings.replace((String)key, (String)value);
+ }
+ return super.replace(key, value);
+ }
+
+ private void implReplaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
+ legacyChanged = true;
+ if (legacyStrings == null) {
+ legacyStrings = new LinkedHashMap<String,String>();
+ } else {
+ legacyStrings.replaceAll((BiFunction<? super String, ? super String, ? extends String>) function);
+ }
+ super.replaceAll(function);
+ }
+
+
+ private Object implMerge(Object key, Object value, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
}
- legacyStrings.put(keyString, (String)value);
+ legacyStrings.merge((String)key, (String)value,
+ (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
+ }
+ return super.merge(key, value, remappingFunction);
+ }
+
+ private Object implCompute(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.computeIfAbsent((String) key,
+ (Function<? super String, ? extends String>) remappingFunction);
+ }
+ return super.compute(key, remappingFunction);
+ }
+
+ private Object implComputeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.computeIfAbsent((String) key,
+ (Function<? super String, ? extends String>) mappingFunction);
+ }
+ return super.computeIfAbsent(key, mappingFunction);
+ }
+
+ private Object implComputeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.computeIfPresent((String) key,
+ (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
+ }
+ return super.computeIfPresent(key, remappingFunction);
+ }
+
+ private Object implPut(Object key, Object value) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.put((String)key, (String)value);
}
return super.put(key, value);
}
+ private Object implPutIfAbsent(Object key, Object value) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.putIfAbsent((String)key, (String)value);
+ }
+ return super.putIfAbsent(key, value);
+ }
+
private void implClear() {
if (legacyStrings != null) {
legacyStrings.clear();
diff --git a/src/share/classes/java/security/SecurityPermission.java b/src/share/classes/java/security/SecurityPermission.java
index bbdccae..5bb7456 100644
--- a/src/share/classes/java/security/SecurityPermission.java
+++ b/src/share/classes/java/security/SecurityPermission.java
@@ -44,7 +44,6 @@
* The following table lists all the possible SecurityPermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- * <P>
*
* <table border=1 cellpadding=5 summary="target name,what the permission allows, and associated risks">
* <tr>
@@ -193,7 +192,6 @@
* associated with classes that have been deprecated: {@link Identity},
* {@link IdentityScope}, {@link Signer}. Use of them is discouraged. See the
* applicable classes for more information.
- * <P>
*
* <table border=1 cellpadding=5 summary="target name,what the permission allows, and associated risks">
* <tr>
diff --git a/src/share/classes/java/security/Signature.java b/src/share/classes/java/security/Signature.java
index a40290f..7c5bd96 100644
--- a/src/share/classes/java/security/Signature.java
+++ b/src/share/classes/java/security/Signature.java
@@ -77,13 +77,13 @@
* (see {@link #initSign(PrivateKey)}
* and {@link #initSign(PrivateKey, SecureRandom)}).
*
- * </ul><p>
+ * </ul>
*
- * <li>Updating<p>
+ * <li>Updating
*
* <p>Depending on the type of initialization, this will update the
* bytes to be signed or verified. See the
- * {@link #update(byte) update} methods.<p>
+ * {@link #update(byte) update} methods.
*
* <li>Signing or Verifying a signature on all updated bytes. See the
* {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
diff --git a/src/share/classes/java/security/SignedObject.java b/src/share/classes/java/security/SignedObject.java
index dba803d..9ac864e 100644
--- a/src/share/classes/java/security/SignedObject.java
+++ b/src/share/classes/java/security/SignedObject.java
@@ -43,7 +43,7 @@
* object passed to the constructor and the {@code verify} method.
* A typical usage for signing is the following:
*
- * <p> <pre>{@code
+ * <pre>{@code
* Signature signingEngine = Signature.getInstance(algorithm,
* provider);
* SignedObject so = new SignedObject(myobject, signingKey,
@@ -53,7 +53,7 @@
* <p> A typical usage for verification is the following (having
* received SignedObject {@code so}):
*
- * <p> <pre>{@code
+ * <pre>{@code
* Signature verificationEngine =
* Signature.getInstance(algorithm, provider);
* if (so.verify(publickey, verificationEngine))
diff --git a/src/share/classes/java/security/acl/Acl.java b/src/share/classes/java/security/acl/Acl.java
index e7b6a21..b9cf004 100644
--- a/src/share/classes/java/security/acl/Acl.java
+++ b/src/share/classes/java/security/acl/Acl.java
@@ -42,27 +42,27 @@
* granted to the associated principal. If negative, the permissions
* are to be denied.<p>
*
- * The ACL Entries in each ACL observe the following rules:<p>
+ * The ACL Entries in each ACL observe the following rules:
*
* <ul> <li>Each principal can have at most one positive ACL entry and
* one negative entry; that is, multiple positive or negative ACL
* entries are not allowed for any principal. Each entry specifies
* the set of permissions that are to be granted (if positive) or
- * denied (if negative). <p>
+ * denied (if negative).
*
* <li>If there is no entry for a particular principal, then the
- * principal is considered to have a null (empty) permission set.<p>
+ * principal is considered to have a null (empty) permission set.
*
* <li>If there is a positive entry that grants a principal a
* particular permission, and a negative entry that denies the
* principal the same permission, the result is as though the
- * permission was never granted or denied. <p>
+ * permission was never granted or denied.
*
* <li>Individual permissions always override permissions of the
* group(s) to which the individual belongs. That is, individual
* negative permissions (specific denial of permissions) override the
* groups' positive permissions. And individual positive permissions
- * override the groups' negative permissions.<p>
+ * override the groups' negative permissions.
*
* </ul>
*
@@ -159,12 +159,12 @@
* Returns an enumeration for the set of allowed permissions for the
* specified principal (representing an entity such as an individual or
* a group). This set of allowed permissions is calculated as
- * follows:<p>
+ * follows:
*
* <ul>
*
* <li>If there is no entry in this Access Control List for the
- * specified principal, an empty permission set is returned.<p>
+ * specified principal, an empty permission set is returned.
*
* <li>Otherwise, the principal's group permission sets are determined.
* (A principal can belong to one or more groups, where a group is a
diff --git a/src/share/classes/java/security/cert/CertificateFactory.java b/src/share/classes/java/security/cert/CertificateFactory.java
index 83ff9fb..f45866d 100644
--- a/src/share/classes/java/security/cert/CertificateFactory.java
+++ b/src/share/classes/java/security/cert/CertificateFactory.java
@@ -63,7 +63,7 @@
* supports those methods), so that each call to
* {@code generateCertificate} consumes only one certificate, and the
* read position of the input stream is positioned to the next certificate in
- * the file:<p>
+ * the file:
*
* <pre>{@code
* FileInputStream fis = new FileInputStream(filename);
@@ -78,7 +78,7 @@
* }</pre>
*
* <p>The following example parses a PKCS#7-formatted certificate reply stored
- * in a file and extracts all the certificates from it:<p>
+ * in a file and extracts all the certificates from it:
*
* <pre>
* FileInputStream fis = new FileInputStream(filename);
diff --git a/src/share/classes/java/security/cert/PKIXRevocationChecker.java b/src/share/classes/java/security/cert/PKIXRevocationChecker.java
index 3046a03..a345c96 100644
--- a/src/share/classes/java/security/cert/PKIXRevocationChecker.java
+++ b/src/share/classes/java/security/cert/PKIXRevocationChecker.java
@@ -299,7 +299,7 @@
/**
* Allow revocation check to succeed if the revocation status cannot be
* determined for one of the following reasons:
- * <p><ul>
+ * <ul>
* <li>The CRL or OCSP response cannot be obtained because of a
* network error.
* <li>The OCSP responder returns one of the following errors
diff --git a/src/share/classes/java/security/cert/PolicyQualifierInfo.java b/src/share/classes/java/security/cert/PolicyQualifierInfo.java
index bc083eb..ec06a88 100644
--- a/src/share/classes/java/security/cert/PolicyQualifierInfo.java
+++ b/src/share/classes/java/security/cert/PolicyQualifierInfo.java
@@ -35,7 +35,7 @@
* structure.
*
* <p>The ASN.1 definition is as follows:
- * <p><pre>
+ * <pre>
* PolicyQualifierInfo ::= SEQUENCE {
* policyQualifierId PolicyQualifierId,
* qualifier ANY DEFINED BY policyQualifierId }
diff --git a/src/share/classes/java/security/cert/TrustAnchor.java b/src/share/classes/java/security/cert/TrustAnchor.java
index fe267a5..c98bf81 100644
--- a/src/share/classes/java/security/cert/TrustAnchor.java
+++ b/src/share/classes/java/security/cert/TrustAnchor.java
@@ -44,7 +44,6 @@
* individual parameters.
* <p>
* <b>Concurrent Access</b>
- * <p>
* <p>All {@code TrustAnchor} objects must be immutable and
* thread-safe. That is, multiple threads may concurrently invoke the
* methods defined in this class on a single {@code TrustAnchor}
diff --git a/src/share/classes/java/security/cert/X509CertSelector.java b/src/share/classes/java/security/cert/X509CertSelector.java
index e44dba1..aae32c9 100644
--- a/src/share/classes/java/security/cert/X509CertSelector.java
+++ b/src/share/classes/java/security/cert/X509CertSelector.java
@@ -359,7 +359,7 @@
* criticality setting, and encapsulating OCTET STRING)
* for a SubjectKeyIdentifier extension.
* The ASN.1 notation for this structure follows.
- * <p>
+ *
* <pre>{@code
* SubjectKeyIdentifier ::= KeyIdentifier
*
@@ -399,7 +399,7 @@
* criticality setting, and encapsulating OCTET STRING)
* for an AuthorityKeyIdentifier extension.
* The ASN.1 notation for this structure follows.
- * <p>
+ *
* <pre>{@code
* AuthorityKeyIdentifier ::= SEQUENCE {
* keyIdentifier [0] KeyIdentifier OPTIONAL,
diff --git a/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java b/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java
index 3908357..e50cfd2 100644
--- a/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java
+++ b/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java
@@ -43,11 +43,11 @@
*
* <li>Get a key pair generator for the DSA algorithm by calling the
* KeyPairGenerator {@code getInstance} method with "DSA"
- * as its argument.<p>
+ * as its argument.
*
* <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
* and calling one of the
- * {@code initialize} methods from this DSAKeyPairGenerator interface.<p>
+ * {@code initialize} methods from this DSAKeyPairGenerator interface.
*
* <li>Generate a key pair by calling the {@code generateKeyPair}
* method from the KeyPairGenerator class.
diff --git a/src/share/classes/java/text/MessageFormat.java b/src/share/classes/java/text/MessageFormat.java
index 402a7fa..2497a49 100644
--- a/src/share/classes/java/text/MessageFormat.java
+++ b/src/share/classes/java/text/MessageFormat.java
@@ -125,7 +125,6 @@
* valid patterns, but <code>"ab {0'}' de"</code>, <code>"ab } de"</code>
* and <code>"''{''"</code> are not.
*
- * <p>
* <dl><dt><b>Warning:</b><dd>The rules for using quotes within message
* format patterns unfortunately have shown to be somewhat confusing.
* In particular, it isn't always obvious to localizers whether single
@@ -146,7 +145,7 @@
* table shows how the values map to {@code Format} instances. Combinations not
* shown in the table are illegal. A <i>SubformatPattern</i> must
* be a valid pattern string for the {@code Format} subclass used.
- * <p>
+ *
* <table border=1 summary="Shows how FormatType and FormatStyle values map to Format instances">
* <tr>
* <th id="ft" class="TableHeadingColor">FormatType
@@ -215,7 +214,6 @@
* <td headers="fs"><i>SubformatPattern</i>
* <td headers="sc">{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
* </table>
- * <p>
*
* <h4>Usage Information</h4>
*
@@ -761,7 +759,7 @@
* as indicated by the first matching line of the following table. An
* argument is <i>unavailable</i> if <code>arguments</code> is
* <code>null</code> or has fewer than argumentIndex+1 elements.
- * <p>
+ *
* <table border=1 summary="Examples of subformat,argument,and formatted text">
* <tr>
* <th>Subformat
diff --git a/src/share/classes/java/text/Normalizer.java b/src/share/classes/java/text/Normalizer.java
index 88fdf2b..a97b4c1 100644
--- a/src/share/classes/java/text/Normalizer.java
+++ b/src/share/classes/java/text/Normalizer.java
@@ -53,12 +53,12 @@
* several different ways in Unicode. For example, take the character A-acute.
* In Unicode, this can be encoded as a single character (the "composed" form):
*
- * <p><pre>
+ * <pre>
* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE</pre>
*
* or as two separate characters (the "decomposed" form):
*
- * <p><pre>
+ * <pre>
* U+0041 LATIN CAPITAL LETTER A
* U+0301 COMBINING ACUTE ACCENT</pre>
*
@@ -72,14 +72,14 @@
* <p>
* Similarly, the string "ffi" can be encoded as three separate letters:
*
- * <p><pre>
+ * <pre>
* U+0066 LATIN SMALL LETTER F
* U+0066 LATIN SMALL LETTER F
* U+0069 LATIN SMALL LETTER I</pre>
*
* or as the single character
*
- * <p><pre>
+ * <pre>
* U+FB03 LATIN SMALL LIGATURE FFI</pre>
*
* The ffi ligature is not a distinct semantic character, and strictly speaking
diff --git a/src/share/classes/java/text/SimpleDateFormat.java b/src/share/classes/java/text/SimpleDateFormat.java
index fa9f673..c510d2d 100644
--- a/src/share/classes/java/text/SimpleDateFormat.java
+++ b/src/share/classes/java/text/SimpleDateFormat.java
@@ -356,7 +356,6 @@
* may be replaced with other, locale dependent, pattern letters.
* <code>SimpleDateFormat</code> does not deal with the localization of text
* other than the pattern letters; that's up to the client of the class.
- * <p>
*
* <h4>Examples</h4>
*
diff --git a/src/share/classes/java/time/Duration.java b/src/share/classes/java/time/Duration.java
index 896a299..0b7fd17 100644
--- a/src/share/classes/java/time/Duration.java
+++ b/src/share/classes/java/time/Duration.java
@@ -141,7 +141,7 @@
/**
* The pattern for parsing.
*/
- private final static Pattern PATTERN =
+ private static final Pattern PATTERN =
Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
"(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
Pattern.CASE_INSENSITIVE);
@@ -554,7 +554,7 @@
* the simple initialization in Duration.
*/
private static class DurationUnits {
- final static List<TemporalUnit> UNITS =
+ static final List<TemporalUnit> UNITS =
Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS));
}
diff --git a/src/share/classes/java/time/OffsetDateTime.java b/src/share/classes/java/time/OffsetDateTime.java
index 755d677..42698d5 100644
--- a/src/share/classes/java/time/OffsetDateTime.java
+++ b/src/share/classes/java/time/OffsetDateTime.java
@@ -1903,9 +1903,9 @@
* <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
* @serialData
* <pre>
- * out.writeByte(10); // identifies a OffsetDateTime
- * out.writeObject(dateTime);
- * out.writeObject(offset);
+ * out.writeByte(10); // identifies an OffsetDateTime
+ * // the <a href="../../serialized-form.html#java.time.LocalDateTime">datetime</a> excluding the one byte header
+ * // the <a href="../../serialized-form.html#java.time.ZoneOffset">offset</a> excluding the one byte header
* </pre>
*
* @return the instance of {@code Ser}, not null
@@ -1924,13 +1924,13 @@
}
void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(dateTime);
- out.writeObject(offset);
+ dateTime.writeExternal(out);
+ offset.writeExternal(out);
}
static OffsetDateTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- LocalDateTime dateTime = (LocalDateTime) in.readObject();
- ZoneOffset offset = (ZoneOffset) in.readObject();
+ LocalDateTime dateTime = LocalDateTime.readExternal(in);
+ ZoneOffset offset = ZoneOffset.readExternal(in);
return OffsetDateTime.of(dateTime, offset);
}
diff --git a/src/share/classes/java/time/OffsetTime.java b/src/share/classes/java/time/OffsetTime.java
index c9601a0..e82ccda 100644
--- a/src/share/classes/java/time/OffsetTime.java
+++ b/src/share/classes/java/time/OffsetTime.java
@@ -1374,9 +1374,9 @@
* <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
* @serialData
* <pre>
- * out.writeByte(9); // identifies a OffsetTime
- * out.writeObject(time);
- * out.writeObject(offset);
+ * out.writeByte(9); // identifies an OffsetTime
+ * // the <a href="../../serialized-form.html#java.time.LocalTime">time</a> excluding the one byte header
+ * // the <a href="../../serialized-form.html#java.time.ZoneOffset">offset</a> excluding the one byte header
* </pre>
*
* @return the instance of {@code Ser}, not null
@@ -1395,13 +1395,13 @@
}
void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(time);
- out.writeObject(offset);
+ time.writeExternal(out);
+ offset.writeExternal(out);
}
static OffsetTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- LocalTime time = (LocalTime) in.readObject();
- ZoneOffset offset = (ZoneOffset) in.readObject();
+ LocalTime time = LocalTime.readExternal(in);
+ ZoneOffset offset = ZoneOffset.readExternal(in);
return OffsetTime.of(time, offset);
}
diff --git a/src/share/classes/java/time/Period.java b/src/share/classes/java/time/Period.java
index 998eb60..bbc1d56 100644
--- a/src/share/classes/java/time/Period.java
+++ b/src/share/classes/java/time/Period.java
@@ -138,13 +138,13 @@
/**
* The pattern for parsing.
*/
- private final static Pattern PATTERN =
+ private static final Pattern PATTERN =
Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)Y)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)W)?(?:([-+]?[0-9]+)D)?", Pattern.CASE_INSENSITIVE);
/**
* The set of supported units.
*/
- private final static List<TemporalUnit> SUPPORTED_UNITS =
+ private static final List<TemporalUnit> SUPPORTED_UNITS =
Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
/**
diff --git a/src/share/classes/java/time/ZoneId.java b/src/share/classes/java/time/ZoneId.java
index 42f3909..aabc7fc 100644
--- a/src/share/classes/java/time/ZoneId.java
+++ b/src/share/classes/java/time/ZoneId.java
@@ -169,60 +169,15 @@
public abstract class ZoneId implements Serializable {
/**
- * A map of zone overrides to enable the older short time-zone names to be used.
- * <p>
- * Use of short zone IDs has been deprecated in {@code java.util.TimeZone}.
- * This map allows the IDs to continue to be used via the
- * {@link #of(String, Map)} factory method.
- * <p>
- * This map contains an older mapping of the IDs, where 'EST', 'MST' and 'HST'
- * map to IDs which include daylight savings.
- * This is in line with versions of TZDB before 2005r.
- * <p>
- * This maps as follows:
- * <ul>
- * <li>EST - America/New_York</li>
- * <li>MST - America/Denver</li>
- * <li>HST - Pacific/Honolulu</li>
- * <li>ACT - Australia/Darwin</li>
- * <li>AET - Australia/Sydney</li>
- * <li>AGT - America/Argentina/Buenos_Aires</li>
- * <li>ART - Africa/Cairo</li>
- * <li>AST - America/Anchorage</li>
- * <li>BET - America/Sao_Paulo</li>
- * <li>BST - Asia/Dhaka</li>
- * <li>CAT - Africa/Harare</li>
- * <li>CNT - America/St_Johns</li>
- * <li>CST - America/Chicago</li>
- * <li>CTT - Asia/Shanghai</li>
- * <li>EAT - Africa/Addis_Ababa</li>
- * <li>ECT - Europe/Paris</li>
- * <li>IET - America/Indiana/Indianapolis</li>
- * <li>IST - Asia/Kolkata</li>
- * <li>JST - Asia/Tokyo</li>
- * <li>MIT - Pacific/Apia</li>
- * <li>NET - Asia/Yerevan</li>
- * <li>NST - Pacific/Auckland</li>
- * <li>PLT - Asia/Karachi</li>
- * <li>PNT - America/Phoenix</li>
- * <li>PRT - America/Puerto_Rico</li>
- * <li>PST - America/Los_Angeles</li>
- * <li>SST - Pacific/Guadalcanal</li>
- * <li>VST - Asia/Ho_Chi_Minh</li>
- * </ul>
- * The map is unmodifiable.
- */
- public static final Map<String, String> OLD_SHORT_IDS;
- /**
* A map of zone overrides to enable the short time-zone names to be used.
* <p>
* Use of short zone IDs has been deprecated in {@code java.util.TimeZone}.
* This map allows the IDs to continue to be used via the
* {@link #of(String, Map)} factory method.
* <p>
- * This map contains a newer mapping of the IDs, where 'EST', 'MST' and 'HST'
- * map to IDs which do not include daylight savings
- * This is in line with TZDB 2005r and later.
+ * This map contains a mapping of the IDs that is in line with TZDB 2005r and
+ * later, where 'EST', 'MST' and 'HST' map to IDs which do not include daylight
+ * savings.
* <p>
* This maps as follows:
* <ul>
@@ -259,42 +214,36 @@
*/
public static final Map<String, String> SHORT_IDS;
static {
- Map<String, String> base = new HashMap<>();
- base.put("ACT", "Australia/Darwin");
- base.put("AET", "Australia/Sydney");
- base.put("AGT", "America/Argentina/Buenos_Aires");
- base.put("ART", "Africa/Cairo");
- base.put("AST", "America/Anchorage");
- base.put("BET", "America/Sao_Paulo");
- base.put("BST", "Asia/Dhaka");
- base.put("CAT", "Africa/Harare");
- base.put("CNT", "America/St_Johns");
- base.put("CST", "America/Chicago");
- base.put("CTT", "Asia/Shanghai");
- base.put("EAT", "Africa/Addis_Ababa");
- base.put("ECT", "Europe/Paris");
- base.put("IET", "America/Indiana/Indianapolis");
- base.put("IST", "Asia/Kolkata");
- base.put("JST", "Asia/Tokyo");
- base.put("MIT", "Pacific/Apia");
- base.put("NET", "Asia/Yerevan");
- base.put("NST", "Pacific/Auckland");
- base.put("PLT", "Asia/Karachi");
- base.put("PNT", "America/Phoenix");
- base.put("PRT", "America/Puerto_Rico");
- base.put("PST", "America/Los_Angeles");
- base.put("SST", "Pacific/Guadalcanal");
- base.put("VST", "Asia/Ho_Chi_Minh");
- Map<String, String> pre = new HashMap<>(base);
- pre.put("EST", "America/New_York");
- pre.put("MST", "America/Denver");
- pre.put("HST", "Pacific/Honolulu");
- OLD_SHORT_IDS = Collections.unmodifiableMap(pre);
- Map<String, String> post = new HashMap<>(base);
- post.put("EST", "-05:00");
- post.put("MST", "-07:00");
- post.put("HST", "-10:00");
- SHORT_IDS = Collections.unmodifiableMap(post);
+ Map<String, String> map = new HashMap<>(64);
+ map.put("ACT", "Australia/Darwin");
+ map.put("AET", "Australia/Sydney");
+ map.put("AGT", "America/Argentina/Buenos_Aires");
+ map.put("ART", "Africa/Cairo");
+ map.put("AST", "America/Anchorage");
+ map.put("BET", "America/Sao_Paulo");
+ map.put("BST", "Asia/Dhaka");
+ map.put("CAT", "Africa/Harare");
+ map.put("CNT", "America/St_Johns");
+ map.put("CST", "America/Chicago");
+ map.put("CTT", "Asia/Shanghai");
+ map.put("EAT", "Africa/Addis_Ababa");
+ map.put("ECT", "Europe/Paris");
+ map.put("IET", "America/Indiana/Indianapolis");
+ map.put("IST", "Asia/Kolkata");
+ map.put("JST", "Asia/Tokyo");
+ map.put("MIT", "Pacific/Apia");
+ map.put("NET", "Asia/Yerevan");
+ map.put("NST", "Pacific/Auckland");
+ map.put("PLT", "Asia/Karachi");
+ map.put("PNT", "America/Phoenix");
+ map.put("PRT", "America/Puerto_Rico");
+ map.put("PST", "America/Los_Angeles");
+ map.put("SST", "Pacific/Guadalcanal");
+ map.put("VST", "Asia/Ho_Chi_Minh");
+ map.put("EST", "-05:00");
+ map.put("MST", "-07:00");
+ map.put("HST", "-10:00");
+ SHORT_IDS = Collections.unmodifiableMap(map);
}
/**
* Serialization version.
@@ -314,7 +263,7 @@
* @throws ZoneRulesException if the converted zone region ID cannot be found
*/
public static ZoneId systemDefault() {
- return ZoneId.of(TimeZone.getDefault().getID(), SHORT_IDS);
+ return TimeZone.getDefault().toZoneId();
}
/**
diff --git a/src/share/classes/java/time/chrono/ChronoPeriodImpl.java b/src/share/classes/java/time/chrono/ChronoPeriodImpl.java
index 221ce74..28cf0b4 100644
--- a/src/share/classes/java/time/chrono/ChronoPeriodImpl.java
+++ b/src/share/classes/java/time/chrono/ChronoPeriodImpl.java
@@ -104,7 +104,7 @@
/**
* The set of supported units.
*/
- private final static List<TemporalUnit> SUPPORTED_UNITS =
+ private static final List<TemporalUnit> SUPPORTED_UNITS =
Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
/**
diff --git a/src/share/classes/java/time/chrono/JapaneseDate.java b/src/share/classes/java/time/chrono/JapaneseDate.java
index ae4708d..c1ed498 100644
--- a/src/share/classes/java/time/chrono/JapaneseDate.java
+++ b/src/share/classes/java/time/chrono/JapaneseDate.java
@@ -140,7 +140,7 @@
/**
* The first day supported by the JapaneseChronology is Meiji 6, January 1st.
*/
- final static LocalDate MEIJI_6_ISODATE = LocalDate.of(1873, 1, 1);
+ static final LocalDate MEIJI_6_ISODATE = LocalDate.of(1873, 1, 1);
//-----------------------------------------------------------------------
/**
diff --git a/src/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
index 29792b8..9b9d963 100644
--- a/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/src/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -557,12 +557,13 @@
* a two digit year parse will be in the range 1950-01-01 to 2049-12-31.
* Only the year would be extracted from the date, thus a base date of
* 1950-08-25 would also parse to the range 1950-01-01 to 2049-12-31.
- * This behaviour is necessary to support fields such as week-based-year
+ * This behavior is necessary to support fields such as week-based-year
* or other calendar systems where the parsed value does not align with
* standard ISO years.
* <p>
* The exact behavior is as follows. Parse the full set of fields and
- * determine the effective chronology. Then convert the base date to the
+ * determine the effective chronology using the last chronology if
+ * it appears more than once. Then convert the base date to the
* effective chronology. Then extract the specified field from the
* chronology-specific base date and use it to determine the
* {@code baseValue} used below.
@@ -2809,9 +2810,19 @@
int setValue(DateTimeParseContext context, long value, int errorPos, int successPos) {
int baseValue = this.baseValue;
if (baseDate != null) {
- // TODO: effective chrono is inaccurate at this point
Chronology chrono = context.getEffectiveChronology();
baseValue = chrono.date(baseDate).get(field);
+
+ // In case the Chronology is changed later, add a callback when/if it changes
+ final long initialValue = value;
+ context.addChronoChangedListener(
+ (_unused) -> {
+ /* Repeat the set of the field using the current Chronology
+ * The success/error position is ignored because the value is
+ * intentionally being overwritten.
+ */
+ setValue(context, initialValue, errorPos, successPos);
+ });
}
int parseLen = successPos - errorPos;
if (parseLen == minWidth && value >= 0) {
diff --git a/src/share/classes/java/time/format/DateTimeParseContext.java b/src/share/classes/java/time/format/DateTimeParseContext.java
index f72ef7b..3157747 100644
--- a/src/share/classes/java/time/format/DateTimeParseContext.java
+++ b/src/share/classes/java/time/format/DateTimeParseContext.java
@@ -61,7 +61,6 @@
*/
package java.time.format;
-import java.time.Duration;
import java.time.ZoneId;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
@@ -69,6 +68,7 @@
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Context object used during date and time parsing.
@@ -105,6 +105,10 @@
* The list of parsed data.
*/
private final ArrayList<Parsed> parsed = new ArrayList<>();
+ /**
+ * List of Consumers<Chronology> to be notified if the Chronology changes.
+ */
+ private ArrayList<Consumer<Chronology>> chronoListeners = null;
/**
* Creates a new instance of the context.
@@ -354,12 +358,36 @@
* <p>
* This stores the chronology that has been parsed.
* No validation is performed other than ensuring it is not null.
+ * <p>
+ * The list of listeners is copied and cleared so that each
+ * listener is called only once. A listener can add itself again
+ * if it needs to be notified of future changes.
*
* @param chrono the parsed chronology, not null
*/
void setParsed(Chronology chrono) {
Objects.requireNonNull(chrono, "chrono");
currentParsed().chrono = chrono;
+ if (chronoListeners != null && !chronoListeners.isEmpty()) {
+ Consumer[] tmp = new Consumer[1];
+ Consumer<Chronology>[] listeners = chronoListeners.toArray(tmp);
+ chronoListeners.clear();
+ for (Consumer<Chronology> l : listeners) {
+ l.accept(chrono);
+ }
+ }
+ }
+
+ /**
+ * Adds a Consumer<Chronology> to the list of listeners to be notified
+ * if the Chronology changes.
+ * @param listener a Consumer<Chronology> to be called when Chronology changes
+ */
+ void addChronoChangedListener(Consumer<Chronology> listener) {
+ if (chronoListeners == null) {
+ chronoListeners = new ArrayList<Consumer<Chronology>>();
+ }
+ chronoListeners.add(listener);
}
/**
diff --git a/src/share/classes/java/time/temporal/TemporalQueries.java b/src/share/classes/java/time/temporal/TemporalQueries.java
index 42fd4ab..6b1777a 100644
--- a/src/share/classes/java/time/temporal/TemporalQueries.java
+++ b/src/share/classes/java/time/temporal/TemporalQueries.java
@@ -341,34 +341,23 @@
/**
* A strict query for the {@code ZoneId}.
*/
- static final TemporalQuery<ZoneId> ZONE_ID = (temporal) -> {
- return temporal.query(ZONE_ID);
- };
+ static final TemporalQuery<ZoneId> ZONE_ID = (temporal) ->
+ temporal.query(TemporalQueries.ZONE_ID);
/**
* A query for the {@code Chronology}.
*/
- static final TemporalQuery<Chronology> CHRONO = (temporal) -> {
- return temporal.query(CHRONO);
- };
+ static final TemporalQuery<Chronology> CHRONO = (temporal) ->
+ temporal.query(TemporalQueries.CHRONO);
/**
* A query for the smallest supported unit.
*/
- static final TemporalQuery<TemporalUnit> PRECISION = (temporal) -> {
- return temporal.query(PRECISION);
- };
+ static final TemporalQuery<TemporalUnit> PRECISION = (temporal) ->
+ temporal.query(TemporalQueries.PRECISION);
//-----------------------------------------------------------------------
/**
- * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
- */
- static final TemporalQuery<ZoneId> ZONE = (temporal) -> {
- ZoneId zone = temporal.query(ZONE_ID);
- return (zone != null ? zone : temporal.query(OFFSET));
- };
-
- /**
* A query for {@code ZoneOffset} returning null if not found.
*/
static final TemporalQuery<ZoneOffset> OFFSET = (temporal) -> {
@@ -379,6 +368,14 @@
};
/**
+ * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
+ */
+ static final TemporalQuery<ZoneId> ZONE = (temporal) -> {
+ ZoneId zone = temporal.query(ZONE_ID);
+ return (zone != null ? zone : temporal.query(OFFSET));
+ };
+
+ /**
* A query for {@code LocalDate} returning null if not found.
*/
static final TemporalQuery<LocalDate> LOCAL_DATE = (temporal) -> {
diff --git a/src/share/classes/java/time/temporal/WeekFields.java b/src/share/classes/java/time/temporal/WeekFields.java
index dcc459a..29dde9c 100644
--- a/src/share/classes/java/time/temporal/WeekFields.java
+++ b/src/share/classes/java/time/temporal/WeekFields.java
@@ -245,15 +245,15 @@
/**
* The field used to access the computed DayOfWeek.
*/
- private transient final TemporalField dayOfWeek = ComputedDayOfField.ofDayOfWeekField(this);
+ private final transient TemporalField dayOfWeek = ComputedDayOfField.ofDayOfWeekField(this);
/**
* The field used to access the computed WeekOfMonth.
*/
- private transient final TemporalField weekOfMonth = ComputedDayOfField.ofWeekOfMonthField(this);
+ private final transient TemporalField weekOfMonth = ComputedDayOfField.ofWeekOfMonthField(this);
/**
* The field used to access the computed WeekOfYear.
*/
- private transient final TemporalField weekOfYear = ComputedDayOfField.ofWeekOfYearField(this);
+ private final transient TemporalField weekOfYear = ComputedDayOfField.ofWeekOfYearField(this);
/**
* The field that represents the week-of-week-based-year.
* <p>
@@ -261,7 +261,7 @@
* <p>
* This unit is an immutable and thread-safe singleton.
*/
- private transient final TemporalField weekOfWeekBasedYear = ComputedDayOfField.ofWeekOfWeekBasedYearField(this);
+ private final transient TemporalField weekOfWeekBasedYear = ComputedDayOfField.ofWeekOfWeekBasedYearField(this);
/**
* The field that represents the week-based-year.
* <p>
@@ -269,7 +269,7 @@
* <p>
* This unit is an immutable and thread-safe singleton.
*/
- private transient final TemporalField weekBasedYear = ComputedDayOfField.ofWeekBasedYearField(this);
+ private final transient TemporalField weekBasedYear = ComputedDayOfField.ofWeekBasedYearField(this);
//-----------------------------------------------------------------------
/**
diff --git a/src/share/classes/java/time/zone/Ser.java b/src/share/classes/java/time/zone/Ser.java
index b2c3b25..31c2f2d 100644
--- a/src/share/classes/java/time/zone/Ser.java
+++ b/src/share/classes/java/time/zone/Ser.java
@@ -171,9 +171,9 @@
* <li><a href="../../../serialized-form.html#java.time.zone.ZoneRules">ZoneRules</a>
* - {@code ZoneRules.of(standardTransitions, standardOffsets, savingsInstantTransitions, wallOffsets, lastRules);}
* <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransition">ZoneOffsetTransition</a>
- * - {@code ;}
+ * - {@code ZoneOffsetTransition of(LocalDateTime.ofEpochSecond(epochSecond), offsetBefore, offsetAfter);}
* <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransitionRule">ZoneOffsetTransitionRule</a>
- * - {@code ;}
+ * - {@code ZoneOffsetTransitionRule.of(month, dom, dow, time, timeEndOfDay, timeDefinition, standardOffset, offsetBefore, offsetAfter);}
* </ul>
* @param in the data to read, not null
*/
diff --git a/src/share/classes/java/time/zone/TzdbZoneRulesProvider.java b/src/share/classes/java/time/zone/TzdbZoneRulesProvider.java
index b40fe98..6a9d012 100644
--- a/src/share/classes/java/time/zone/TzdbZoneRulesProvider.java
+++ b/src/share/classes/java/time/zone/TzdbZoneRulesProvider.java
@@ -62,6 +62,7 @@
package java.time.zone;
import java.io.ByteArrayInputStream;
+import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -107,7 +108,8 @@
try {
String libDir = System.getProperty("java.home") + File.separator + "lib";
try (DataInputStream dis = new DataInputStream(
- new FileInputStream(new File(libDir, "tzdb.dat")))) {
+ new BufferedInputStream(new FileInputStream(
+ new File(libDir, "tzdb.dat"))))) {
load(dis);
}
} catch (Exception ex) {
diff --git a/src/share/classes/java/time/zone/ZoneOffsetTransition.java b/src/share/classes/java/time/zone/ZoneOffsetTransition.java
index 04192da..79cb5c8 100644
--- a/src/share/classes/java/time/zone/ZoneOffsetTransition.java
+++ b/src/share/classes/java/time/zone/ZoneOffsetTransition.java
@@ -191,7 +191,7 @@
* out.writeByte(2); // identifies a ZoneOffsetTransition
* out.writeEpochSec(toEpochSecond);
* out.writeOffset(offsetBefore);
- * out.writeOfset(offsetAfter);
+ * out.writeOffset(offsetAfter);
* }
* </pre>
* @return the replacing object, not null
diff --git a/src/share/classes/java/util/Base64.java b/src/share/classes/java/util/Base64.java
index 39da03b..db28138 100644
--- a/src/share/classes/java/util/Base64.java
+++ b/src/share/classes/java/util/Base64.java
@@ -40,7 +40,6 @@
* <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a> and
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
*
- * <p>
* <ul>
* <li><a name="basic"><b>Basic</b></a>
* <p> Uses "The Base64 Alphabet" as specified in Table 1 of
@@ -128,7 +127,7 @@
* character of "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045.
*/
- public static Encoder getEncoder(int lineLength, byte[] lineSeparator) {
+ public static Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) {
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
@@ -620,11 +619,20 @@
* required. So if the final unit of the encoded byte data only has
* two or three Base64 characters (without the corresponding padding
* character(s) padded), they are decoded as if followed by padding
- * character(s). If there is padding character present in the
- * final unit, the correct number of padding character(s) must be
- * present, otherwise {@code IllegalArgumentException} (
- * {@code IOException} when reading from a Base64 stream) is thrown
- * during decoding.
+ * character(s).
+ * <p>
+ * For decoders that use the <a href="#basic">Basic</a> and
+ * <a href="#url">URL and Filename safe</a> type base64 scheme, and
+ * if there is padding character present in the final unit, the
+ * correct number of padding character(s) must be present, otherwise
+ * {@code IllegalArgumentException} ({@code IOException} when reading
+ * from a Base64 stream) is thrown during decoding.
+ * <p>
+ * Decoders that use the <a href="#mime">MIME</a> type base64 scheme
+ * are more lenient when decoding the padding character(s). If the
+ * padding character(s) is incorrectly encoded, the first padding
+ * character encountered is interpreted as the end of the encoded byte
+ * data, the decoding operation will then end and return normally.
*
* <p> Instances of {@link Decoder} class are safe for use by
* multiple concurrent threads.
@@ -903,8 +911,9 @@
int b = sa[sp++] & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte
- if (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
- shiftto == 18) {
+ if (!isMIME &&
+ (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
+ shiftto == 18)) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
@@ -943,11 +952,12 @@
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
- while (sp < sl) {
- if (isMIME && base64[sa[sp++]] < 0)
- continue;
- throw new IllegalArgumentException(
- "Input byte array has incorrect ending byte at " + sp);
+ if (sp < sl) {
+ if (isMIME)
+ sp = sl;
+ else
+ throw new IllegalArgumentException(
+ "Input byte array has incorrect ending byte at " + sp);
}
mark = sp;
return dp - dp0;
@@ -972,8 +982,9 @@
int b = src.get(sp++) & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte
- if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
- shiftto == 18) {
+ if (!isMIME &&
+ (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
+ shiftto == 18)) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
@@ -1012,11 +1023,12 @@
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
- while (sp < sl) {
- if (isMIME && base64[src.get(sp++)] < 0)
- continue;
- throw new IllegalArgumentException(
- "Input byte array has incorrect ending byte at " + sp);
+ if (sp < sl) {
+ if (isMIME)
+ sp = sl;
+ else
+ throw new IllegalArgumentException(
+ "Input byte array has incorrect ending byte at " + sp);
}
mark = sp;
return dp - dp0;
@@ -1072,14 +1084,15 @@
while (sp < sl) {
int b = src[sp++] & 0xff;
if ((b = base64[b]) < 0) {
- if (b == -2) { // padding byte '='
- // xx= shiftto==6&&sp==sl missing last =
- // xx=y shiftto==6 last is not =
- // = shiftto==18 unnecessary padding
- // x= shiftto==12 be taken care later
- // together with single x, invalid anyway
- if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
- shiftto == 18) {
+ if (b == -2) { // padding byte '='
+ if (!isMIME && // be lenient for rfc2045
+ // = shiftto==18 unnecessary padding
+ // x= shiftto==12 a dangling single x
+ // x to be handled together with non-padding case
+ // xx= shiftto==6&&sp==sl missing last =
+ // xx=y shiftto==6 last is not =
+ (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
+ shiftto == 18)) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
@@ -1109,14 +1122,14 @@
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
} else if (shiftto == 12) {
+ // dangling single "x", throw exception even in lenient mode,
+ // it's incorrectly encoded.
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
// anything left is invalid, if is not MIME.
- // if MIME, ignore all non-base64 character
- while (sp < sl) {
- if (isMIME && base64[src[sp++]] < 0)
- continue;
+ // if MIME (lenient), just ignore all leftover
+ if (sp < sl && !isMIME) {
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
@@ -1286,7 +1299,7 @@
if (nextin == 12)
throw new IOException("Base64 stream has one un-decoded dangling byte.");
// treat ending xx/xxx without padding character legal.
- // same logic as v == 'v' below
+ // same logic as v == '=' below
b[off++] = (byte)(bits >> (16));
len--;
if (nextin == 0) { // only one padding byte
@@ -1305,21 +1318,31 @@
}
if (v == '=') { // padding byte(s)
// = shiftto==18 unnecessary padding
- // x= shiftto==12 invalid unit
+ // x= shiftto==12 dangling x, invalid unit
// xx= shiftto==6 && missing last '='
- // xx=y or last is not '='
+ // xx=y or last is not '='
if (nextin == 18 || nextin == 12 ||
nextin == 6 && is.read() != '=') {
- throw new IOException("Illegal base64 ending sequence:" + nextin);
- }
- b[off++] = (byte)(bits >> (16));
- len--;
- if (nextin == 0) { // only one padding byte
- if (len == 0) { // no enough output space
- bits >>= 8; // shift to lowest byte
- nextout = 0;
- } else {
- b[off++] = (byte) (bits >> 8);
+ if (!isMIME || nextin == 12) {
+ throw new IOException("Illegal base64 ending sequence:" + nextin);
+ } else if (nextin != 18) {
+ // lenient mode for mime
+ // (1) handle the "unnecessary padding in "xxxx ="
+ // case as the eof (nextin == 18)
+ // (2) decode "xx=" and "xx=y" normally
+ b[off++] = (byte)(bits >> (16));
+ len--;
+ }
+ } else {
+ b[off++] = (byte)(bits >> (16));
+ len--;
+ if (nextin == 0) { // only one padding byte
+ if (len == 0) { // no enough output space
+ bits >>= 8; // shift to lowest byte
+ nextout = 0;
+ } else {
+ b[off++] = (byte) (bits >> 8);
+ }
}
}
eof = true;
diff --git a/src/share/classes/java/util/BitSet.java b/src/share/classes/java/util/BitSet.java
index c7c3143..721d160 100644
--- a/src/share/classes/java/util/BitSet.java
+++ b/src/share/classes/java/util/BitSet.java
@@ -1164,10 +1164,10 @@
* <p>Example:
* <pre>
* BitSet drPepper = new BitSet();</pre>
- * Now {@code drPepper.toString()} returns "{@code {}}".<p>
+ * Now {@code drPepper.toString()} returns "{@code {}}".
* <pre>
* drPepper.set(2);</pre>
- * Now {@code drPepper.toString()} returns "{@code {2}}".<p>
+ * Now {@code drPepper.toString()} returns "{@code {2}}".
* <pre>
* drPepper.set(4);
* drPepper.set(10);</pre>
diff --git a/src/share/classes/java/util/Deque.java b/src/share/classes/java/util/Deque.java
index f651141..3ed3ab8 100644
--- a/src/share/classes/java/util/Deque.java
+++ b/src/share/classes/java/util/Deque.java
@@ -56,7 +56,6 @@
* <p>The twelve methods described above are summarized in the
* following table:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of Deque methods</caption>
* <tr>
@@ -100,7 +99,6 @@
* inherited from the {@code Queue} interface are precisely equivalent to
* {@code Deque} methods as indicated in the following table:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Comparison of Queue and Deque methods</caption>
* <tr>
@@ -139,7 +137,6 @@
* beginning of the deque. Stack methods are precisely equivalent to
* {@code Deque} methods as indicated in the table below:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Comparison of Stack and Deque methods</caption>
* <tr>
diff --git a/src/share/classes/java/util/DoubleSummaryStatistics.java b/src/share/classes/java/util/DoubleSummaryStatistics.java
index 947f47c..be9d4b5 100644
--- a/src/share/classes/java/util/DoubleSummaryStatistics.java
+++ b/src/share/classes/java/util/DoubleSummaryStatistics.java
@@ -127,7 +127,7 @@
* numerical sum compared to a simple summation of {@code double}
* values.
*
- * @apiNote Sorting values by increasing absolute magnitude tends to yield
+ * @apiNote Values sorted by increasing absolute magnitude tend to yield
* more accurate results.
*
* @return the sum of values, or zero if none
diff --git a/src/share/classes/java/util/Formatter.java b/src/share/classes/java/util/Formatter.java
index a94234a..7b6e1d1 100644
--- a/src/share/classes/java/util/Formatter.java
+++ b/src/share/classes/java/util/Formatter.java
@@ -131,7 +131,7 @@
* import static java.util.Calendar.*;
*
* Calendar c = new GregorianCalendar(1995, MAY, 23);
- * String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
+ * String s = String.format("Duke's Birthday: %1$tb %1$te, %1$tY", c);
* // -> s == "Duke's Birthday: May 23, 1995"
* </pre></blockquote>
*
@@ -253,7 +253,7 @@
* <li> <b>Integral</b> - may be applied to Java integral types: {@code byte},
* {@link Byte}, {@code short}, {@link Short}, {@code int} and {@link
* Integer}, {@code long}, {@link Long}, and {@link java.math.BigInteger
- * BigInteger}
+ * BigInteger} (but not {@code char} or {@link Character})
*
* <li><b>Floating Point</b> - may be applied to Java floating-point types:
* {@code float}, {@link Float}, {@code double}, {@link Double}, and {@link
@@ -899,7 +899,7 @@
* <table cellpadding=5 summary="IntConv">
*
* <tr><td valign="top"> {@code 'd'}
- * <td valign="top"> <tt>'\u0054'</tt>
+ * <td valign="top"> <tt>'\u0064'</tt>
* <td> Formats the argument as a decimal integer. The <a
* href="#L10nAlgorithm">localization algorithm</a> is applied.
*
@@ -1057,7 +1057,7 @@
* <table cellpadding=5 summary="BIntConv">
*
* <tr><td valign="top"> {@code 'd'}
- * <td valign="top"> <tt>'\u0054'</tt>
+ * <td valign="top"> <tt>'\u0064'</tt>
* <td> Requires the output to be formatted as a decimal integer. The <a
* href="#L10nAlgorithm">localization algorithm</a> is applied.
*
diff --git a/src/share/classes/java/util/HashMap.java b/src/share/classes/java/util/HashMap.java
index db39a92..1183952 100644
--- a/src/share/classes/java/util/HashMap.java
+++ b/src/share/classes/java/util/HashMap.java
@@ -915,7 +915,7 @@
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator<K> spliterator() {
- return new KeySpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super K> action) {
Node<K,V>[] tab;
@@ -959,7 +959,7 @@
public final Iterator<V> iterator() { return new ValueIterator(); }
public final boolean contains(Object o) { return containsValue(o); }
public final Spliterator<V> spliterator() {
- return new ValueSpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super V> action) {
Node<K,V>[] tab;
@@ -1022,7 +1022,7 @@
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
- return new EntrySpliterator<K,V>(HashMap.this, 0, -1, 0, 0);
+ return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
Node<K,V>[] tab;
@@ -1042,19 +1042,23 @@
// Overrides of JDK8 Map extension methods
+ @Override
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
+ @Override
public V putIfAbsent(K key, V value) {
return putVal(hash(key), key, value, true, true);
}
+ @Override
public boolean remove(Object key, Object value) {
return removeNode(hash(key), key, value, true, true) != null;
}
+ @Override
public boolean replace(K key, V oldValue, V newValue) {
Node<K,V> e; V v;
if ((e = getNode(hash(key), key)) != null &&
@@ -1066,6 +1070,7 @@
return false;
}
+ @Override
public V replace(K key, V value) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) != null) {
@@ -1077,6 +1082,7 @@
return null;
}
+ @Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
if (mappingFunction == null)
@@ -1150,6 +1156,7 @@
return null;
}
+ @Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (remappingFunction == null)
@@ -1202,6 +1209,7 @@
return v;
}
+ @Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
if (remappingFunction == null)
@@ -1230,7 +1238,11 @@
}
}
if (old != null) {
- V v = remappingFunction.apply(old.value, value);
+ V v;
+ if (old.value != null)
+ v = remappingFunction.apply(old.value, value);
+ else
+ v = value;
if (v != null) {
old.value = v;
afterNodeAccess(old);
@@ -1254,6 +1266,7 @@
return value;
}
+ @Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Node<K,V>[] tab;
if (action == null)
@@ -1269,6 +1282,7 @@
}
}
+ @Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Node<K,V>[] tab;
if (function == null)
@@ -1295,6 +1309,7 @@
* @return a shallow copy of this map
*/
@SuppressWarnings("unchecked")
+ @Override
public Object clone() {
HashMap<K,V> result;
try {
@@ -1496,7 +1511,7 @@
public KeySpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
- new KeySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ new KeySpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
@@ -1568,7 +1583,7 @@
public ValueSpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
- new ValueSpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
@@ -1639,7 +1654,7 @@
public EntrySpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
- new EntrySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
+ new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
@@ -1714,22 +1729,22 @@
// Create a regular (non-tree) node
Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
- return new Node<K,V>(hash, key, value, next);
+ return new Node<>(hash, key, value, next);
}
// For conversion from TreeNodes to plain nodes
Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
- return new Node<K,V>(p.hash, p.key, p.value, next);
+ return new Node<>(p.hash, p.key, p.value, next);
}
// Create a tree bin node
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
- return new TreeNode<K,V>(hash, key, value, next);
+ return new TreeNode<>(hash, key, value, next);
}
// For treeifyBin
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
- return new TreeNode<K,V>(p.hash, p.key, p.value, next);
+ return new TreeNode<>(p.hash, p.key, p.value, next);
}
/**
diff --git a/src/share/classes/java/util/Iterator.java b/src/share/classes/java/util/Iterator.java
index 4420d04..7d2daf8 100644
--- a/src/share/classes/java/util/Iterator.java
+++ b/src/share/classes/java/util/Iterator.java
@@ -94,10 +94,10 @@
}
/**
- * Performs the given action for each remaining element, in the order
- * elements occur when iterating, until all elements have been processed or
- * the action throws an exception. Errors or runtime exceptions thrown by
- * the action are relayed to the caller.
+ * Performs the given action for each remaining element until all elements
+ * have been processed or the action throws an exception. Actions are
+ * performed in the order of iteration, if that order is specified.
+ * Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
diff --git a/src/share/classes/java/util/List.java b/src/share/classes/java/util/List.java
index 42a1acf..5cbd044 100644
--- a/src/share/classes/java/util/List.java
+++ b/src/share/classes/java/util/List.java
@@ -192,8 +192,9 @@
* The following code can be used to dump the list into a newly
* allocated array of <tt>String</tt>:
*
- * <pre>
- * String[] y = x.toArray(new String[0]);</pre>
+ * <pre>{@code
+ * String[] y = x.toArray(new String[0]);
+ * }</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
@@ -383,14 +384,13 @@
*
* @implSpec
* The default implementation is equivalent to, for this {@code list}:
- * <pre>
- * {@code
- * final ListIterator<E> li = list.listIterator();
- * while (li.hasNext()) {
- * li.set(operator.apply(li.next()));
- * }
- * }
- * </pre>
+ * <pre>{@code
+ * final ListIterator<E> li = list.listIterator();
+ * while (li.hasNext()) {
+ * li.set(operator.apply(li.next()));
+ * }
+ * }</pre>
+ *
* If the list's list-iterator does not support the {@code set} operation
* then an {@code UnsupportedOperationException} will be thrown when
* replacing the first element.
@@ -469,11 +469,11 @@
/**
* Returns the hash code value for this list. The hash code of a list
* is defined to be the result of the following calculation:
- * <pre>
- * int hashCode = 1;
- * for (E e : list)
- * hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
- * </pre>
+ * <pre>{@code
+ * int hashCode = 1;
+ * for (E e : list)
+ * hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
+ * }</pre>
* This ensures that <tt>list1.equals(list2)</tt> implies that
* <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists,
* <tt>list1</tt> and <tt>list2</tt>, as required by the general
@@ -640,9 +640,9 @@
* a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom
* removes a range of elements from a list:
- * <pre>
+ * <pre>{@code
* list.subList(from, to).clear();
- * </pre>
+ * }</pre>
* Similar idioms may be constructed for <tt>indexOf</tt> and
* <tt>lastIndexOf</tt>, and all of the algorithms in the
* <tt>Collections</tt> class can be applied to a subList.<p>
diff --git a/src/share/classes/java/util/Locale.java b/src/share/classes/java/util/Locale.java
index 48deceb..f1acc5b 100644
--- a/src/share/classes/java/util/Locale.java
+++ b/src/share/classes/java/util/Locale.java
@@ -1248,7 +1248,7 @@
* Returns a string representation of this <code>Locale</code>
* object, consisting of language, country, variant, script,
* and extensions as below:
- * <p><blockquote>
+ * <blockquote>
* language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
* </blockquote>
*
@@ -2199,7 +2199,7 @@
* are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
* fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
* "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
- * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
+ * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
* for more information.
*
* @return an instance of <code>Locale</code> equivalent to
diff --git a/src/share/classes/java/util/Map.java b/src/share/classes/java/util/Map.java
index d67e58d..5c3f954 100644
--- a/src/share/classes/java/util/Map.java
+++ b/src/share/classes/java/util/Map.java
@@ -562,11 +562,11 @@
// Defaultable methods
/**
- * Returns the value to which the specified key is mapped,
- * or {@code defaultValue} if this map contains no mapping
- * for the key.
+ * Returns the value to which the specified key is mapped, or
+ * {@code defaultValue} if this map contains no mapping for the key.
*
- * <p>The default implementation makes no guarantees about synchronization
+ * @implSpec
+ * The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing
* atomicity guarantees must override this method and document its
* concurrency properties.
@@ -591,27 +591,24 @@
}
/**
- * Performs the given action on each entry in this map, in the order entries
- * are returned by an entry set iterator (which may be unspecified), until
- * all entries have been processed or the action throws an {@code Exception}.
+ * Performs the given action for each entry in this map until all entries
+ * have been processed or the action throws an exception. Unless
+ * otherwise specified by the implementing class, actions are performed in
+ * the order of entry set iteration (if an iteration order is specified.)
* Exceptions thrown by the action are relayed to the caller.
*
- * <p>The default implementation should be overridden by implementations if
- * they can provide a more performant implementation than an iterator-based
- * one.
- *
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
- *
- * @implSpec The default implementation is equivalent to, for this
- * {@code map}:
+ * @implSpec
+ * The default implementation is equivalent to, for this {@code map}:
* <pre> {@code
* for ((Map.Entry<K, V> entry : map.entrySet())
* action.accept(entry.getKey(), entry.getValue());
* }</pre>
*
+ * The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param action The action to be performed for each entry
* @throws NullPointerException if the specified action is null
* @throws ConcurrentModificationException if an entry is found to be
@@ -636,14 +633,9 @@
/**
* Replaces each entry's value with the result of invoking the given
- * function on that entry, in the order entries are returned by an entry
- * set iterator, until all entries have been processed or the function
- * throws an exception.
- *
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
+ * function on that entry until all entries have been processed or the
+ * function throws an exception. Exceptions thrown by the function are
+ * relayed to the caller.
*
* @implSpec
* <p>The default implementation is equivalent to, for this {@code map}:
@@ -652,6 +644,11 @@
* entry.setValue(function.apply(entry.getKey(), entry.getValue()));
* }</pre>
*
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param function the function to apply to each entry
* @throws UnsupportedOperationException if the {@code set} operation
* is not supported by this map's entry set iterator.
@@ -703,22 +700,23 @@
* to {@code null}) associates it with the given value and returns
* {@code null}, else returns the current value.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
- *
* @implSpec
* The default implementation is equivalent to, for this {@code
* map}:
*
* <pre> {@code
- * if (map.get(key) == null)
- * return map.put(key, value);
- * else
- * return map.get(key);
+ * V v = map.get(key);
+ * if (v == null)
+ * v = map.put(key, value);
+ *
+ * return v;
* }</pre>
*
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
@@ -738,16 +736,12 @@
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
* (<a href="Collection.html#optional-restrictions">optional</a>)
- * @throws ConcurrentModificationException if a modification of the map is
- * detected during insertion of the value.
* @since 1.8
*/
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
- if (put(key, value) != null) {
- throw new ConcurrentModificationException();
- }
+ v = put(key, value);
}
return v;
@@ -757,11 +751,6 @@
* Removes the entry for the specified key only if it is currently
* mapped to the specified value.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
- *
* @implSpec
* The default implementation is equivalent to, for this {@code map}:
*
@@ -773,6 +762,11 @@
* return false;
* }</pre>
*
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key
* @return {@code true} if the value was removed
@@ -801,11 +795,6 @@
* Replaces the entry for the specified key only if currently
* mapped to the specified value.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
- *
* @implSpec
* The default implementation is equivalent to, for this {@code map}:
*
@@ -821,6 +810,11 @@
* for maps that do not support null values if oldValue is null unless
* newValue is also null.
*
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
@@ -853,11 +847,6 @@
* Replaces the entry for the specified key only if it is
* currently mapped to some value.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties.
- *
* @implSpec
* The default implementation is equivalent to, for this {@code map}:
*
@@ -868,6 +857,11 @@
* return null;
* }</pre>
*
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
* @param key key with which the specified value is associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
@@ -888,14 +882,17 @@
* @since 1.8
*/
default V replace(K key, V value) {
- return containsKey(key) ? put(key, value) : null;
+ V curValue;
+ if (((curValue = get(key)) != null) || containsKey(key)) {
+ curValue = put(key, value);
+ }
+ return curValue;
}
/**
- * If the specified key is not already associated with a value (or
- * is mapped to {@code null}), attempts to compute its value using
- * the given mapping function and enters it into this map unless
- * {@code null}.
+ * If the specified key is not already associated with a value (or is mapped
+ * to {@code null}), attempts to compute its value using the given mapping
+ * function and enters it into this map unless {@code null}.
*
* <p>If the function returns {@code null} no mapping is recorded. If
* the function itself throws an (unchecked) exception, the
@@ -907,35 +904,42 @@
* map.computeIfAbsent(key, k -> new Value(f(k)));
* }</pre>
*
+ * <p>Or to implement a multi-value map, {@code Map<K,Collection<V>>},
+ * supporting multiple values per key:
+ *
+ * <pre> {@code
+ * map.computeIfAbsent(key, k -> new HashSet<V>()).add(v);
+ * }</pre>
+ *
+ *
+ * @implSpec
+ * The default implementation is equivalent to the following steps for this
+ * {@code map}, then returning the current value or {@code null} if now
+ * absent:
+ *
+ * <pre> {@code
+ * if (map.get(key) == null) {
+ * V newValue = mappingFunction.apply(key);
+ * if (newValue != null)
+ * map.put(key, newValue);
+ * }
+ * }</pre>
+ *
* <p>The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing
* atomicity guarantees must override this method and document its
* concurrency properties. In particular, all implementations of
* subinterface {@link java.util.concurrent.ConcurrentMap} must document
* whether the function is applied once atomically only if the value is not
- * present. Any class that permits null values must document
- * whether and how this method distinguishes absence from null mappings.
- *
- * @implSpec
- * The default implementation is equivalent to the following
- * steps for this {@code map}, then returning the current value or
- * {@code null} if now absent:
- *
- * <pre> {@code
- * if (map.get(key) == null) {
- * V newValue = mappingFunction.apply(key);
- * if (newValue != null)
- * map.putIfAbsent(key, newValue);
- * }
- * }</pre>
+ * present.
*
* @param key key with which the specified value is to be associated
* @param mappingFunction the function to compute a value
* @return the current (existing or computed) value associated with
* the specified key, or null if the computed value is null
* @throws NullPointerException if the specified key is null and
- * this map does not support null keys, or the
- * mappingFunction is null
+ * this map does not support null keys, or the mappingFunction
+ * is null
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* (<a href="Collection.html#optional-restrictions">optional</a>)
@@ -947,10 +951,16 @@
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
- V v, newValue;
- return ((v = get(key)) == null &&
- (newValue = mappingFunction.apply(key)) != null &&
- (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
+ V v;
+ if ((v = get(key)) == null) {
+ V newValue;
+ if ((newValue = mappingFunction.apply(key)) != null) {
+ put(key, newValue);
+ return newValue;
+ }
+ }
+
+ return v;
}
/**
@@ -960,6 +970,22 @@
* <p>If the function returns {@code null}, the mapping is removed. If the
* function itself throws an (unchecked) exception, the exception is
* rethrown, and the current mapping is left unchanged.
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the following
+ * steps for this {@code map}, then returning the current value or
+ * {@code null} if now absent:
+ *
+ * <pre> {@code
+ * if (map.get(key) != null) {
+ * V oldValue = map.get(key);
+ * V newValue = remappingFunction.apply(key, oldValue);
+ * if (newValue != null)
+ * map.put(key, newValue);
+ * else
+ * map.remove(key);
+ * }
+ * }</pre>
*
* <p>The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing
@@ -967,27 +993,7 @@
* concurrency properties. In particular, all implementations of
* subinterface {@link java.util.concurrent.ConcurrentMap} must document
* whether the function is applied once atomically only if the value is not
- * present. Any class that permits null values must document
- * whether and how this method distinguishes absence from null mappings.
- *
- * @implSpec
- * The default implementation is equivalent to performing the
- * following steps for this {@code map}, then returning the
- * current value or {@code null} if now absent:
- *
- * <pre> {@code
- * if (map.get(key) != null) {
- * V oldValue = map.get(key);
- * V newValue = remappingFunction.apply(key, oldValue);
- * if (newValue != null)
- * map.replace(key, oldValue, newValue);
- * else
- * map.remove(key, oldValue);
- * }
- * }</pre>
- *
- * In concurrent contexts, the default implementation may retry
- * these steps when multiple threads attempt updates.
+ * present.
*
* @param key key with which the specified value is to be associated
* @param remappingFunction the function to compute a value
@@ -1007,22 +1013,25 @@
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
- while ((oldValue = get(key)) != null) {
+ if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
- if (replace(key, oldValue, newValue))
- return newValue;
- } else if (remove(key, oldValue))
+ put(key, newValue);
+ return newValue;
+ } else {
+ remove(key);
return null;
+ }
+ } else {
+ return null;
}
- return oldValue;
}
/**
- * Attempts to compute a mapping for the specified key and its
- * current mapped value (or {@code null} if there is no current
- * mapping). For example, to either create or append a {@code
- * String msg} to a value mapping:
+ * Attempts to compute a mapping for the specified key and its current
+ * mapped value (or {@code null} if there is no current mapping). For
+ * example, to either create or append a {@code String} msg to a value
+ * mapping:
*
* <pre> {@code
* map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
@@ -1033,15 +1042,6 @@
* (unchecked) exception, the exception is rethrown, and the current mapping
* is left unchanged.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties. In particular, all implementations of
- * subinterface {@link java.util.concurrent.ConcurrentMap} must document
- * whether the function is applied once atomically only if the value is not
- * present. Any class that permits null values must document
- * whether and how this method distinguishes absence from null mappings.
- *
* @implSpec
* The default implementation is equivalent to performing the following
* steps for this {@code map}, then returning the current value or
@@ -1052,19 +1052,24 @@
* V newValue = remappingFunction.apply(key, oldValue);
* if (oldValue != null ) {
* if (newValue != null)
- * map.replace(key, oldValue, newValue);
+ * map.put(key, newValue);
* else
- * map.remove(key, oldValue);
+ * map.remove(key);
* } else {
* if (newValue != null)
- * map.putIfAbsent(key, newValue);
+ * map.put(key, newValue);
* else
* return null;
* }
* }</pre>
*
- * In concurrent contexts, the default implementation may retry
- * these steps when multiple threads attempt updates.
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present.
*
* @param key key with which the specified value is to be associated
* @param remappingFunction the function to compute a value
@@ -1084,44 +1089,22 @@
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
- for (;;) {
- V newValue = remappingFunction.apply(key, oldValue);
- if (newValue == null) {
- // delete mapping
- if(oldValue != null || containsKey(key)) {
- // something to remove
- if (remove(key, oldValue)) {
- // removed the old value as expected
- return null;
- }
- // some other value replaced old value. try again.
- oldValue = get(key);
- } else {
- // nothing to do. Leave things as they were.
- return null;
- }
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (newValue == null) {
+ // delete mapping
+ if (oldValue != null || containsKey(key)) {
+ // something to remove
+ remove(key);
+ return null;
} else {
- // add or replace old mapping
- if (oldValue != null) {
- // replace
- if (replace(key, oldValue, newValue)) {
- // replaced as expected.
- return newValue;
- }
-
- // some other value replaced old value. try again.
- oldValue = get(key);
- } else {
- // add (replace if oldValue was null)
- if ((oldValue = putIfAbsent(key, newValue)) == null) {
- // replaced
- return newValue;
- }
-
- // some other value replaced old value. try again.
- }
+ // nothing to do. Leave things as they were.
+ return null;
}
+ } else {
+ // add or replace old mapping
+ put(key, newValue);
+ return newValue;
}
}
@@ -1143,15 +1126,6 @@
* (unchecked) exception, the exception is rethrown, and the current mapping
* is left unchanged.
*
- * <p>The default implementation makes no guarantees about synchronization
- * or atomicity properties of this method. Any implementation providing
- * atomicity guarantees must override this method and document its
- * concurrency properties. In particular, all implementations of
- * subinterface {@link java.util.concurrent.ConcurrentMap} must document
- * whether the function is applied once atomically only if the value is not
- * present. Any class that permits null values must document
- * whether and how this method distinguishes absence from null mappings.
- *
* @implSpec
* The default implementation is equivalent to performing the
* following steps for this {@code map}, then returning the
@@ -1162,15 +1136,20 @@
* V newValue = (oldValue == null) ? value :
* remappingFunction.apply(oldValue, value);
* if (newValue == null)
- * map.remove(key, oldValue);
+ * map.remove(key);
* else if (oldValue == null)
- * map.putIfAbsent(key, newValue);
+ * map.remove(key);
* else
- * map.replace(key, oldValue, newValue);
+ * map.put(key, newValue);
* }</pre>
*
- * In concurrent contexts, the default implementation may retry
- * these steps when multiple threads attempt updates.
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present.
*
* @param key key with which the specified value is to be associated
* @param value the value to use if absent
@@ -1183,32 +1162,30 @@
* prevents it from being stored in this map
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified key is null and
- * this map does not support null keys, or the
- * remappingFunction is null
+ * this map does not support null keys, or the remappingFunction
+ * is null
* @since 1.8
*/
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
- for (;;) {
- if (oldValue != null) {
- V newValue = remappingFunction.apply(oldValue, value);
- if (newValue != null) {
- if (replace(key, oldValue, newValue))
- return newValue;
- } else if (remove(key, oldValue)) {
- return null;
- }
- oldValue = get(key);
+ if (oldValue != null) {
+ V newValue = remappingFunction.apply(oldValue, value);
+ if (newValue != null) {
+ put(key, newValue);
+ return newValue;
} else {
- if (value == null) {
- return null;
- }
-
- if ((oldValue = putIfAbsent(key, value)) == null) {
- return value;
- }
+ remove(key);
+ return null;
+ }
+ } else {
+ if (value == null) {
+ remove(key);
+ return null;
+ } else {
+ put(key, value);
+ return value;
}
}
}
diff --git a/src/share/classes/java/util/PrimitiveIterator.java b/src/share/classes/java/util/PrimitiveIterator.java
index 6689614..2bc864a 100644
--- a/src/share/classes/java/util/PrimitiveIterator.java
+++ b/src/share/classes/java/util/PrimitiveIterator.java
@@ -76,6 +76,7 @@
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
*/
+ @SuppressWarnings("overloads")
void forEachRemaining(T_CONS action);
/**
@@ -93,10 +94,10 @@
int nextInt();
/**
- * Performs the given action for each remaining element, in the order
- * elements occur when iterating, until all elements have been processed
- * or the action throws an exception. Errors or runtime exceptions
- * thrown by the action are relayed to the caller.
+ * Performs the given action for each remaining element until all elements
+ * have been processed or the action throws an exception. Actions are
+ * performed in the order of iteration, if that order is specified.
+ * Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
@@ -167,10 +168,10 @@
long nextLong();
/**
- * Performs the given action for each remaining element, in the order
- * elements occur when iterating, until all elements have been processed
- * or the action throws an exception. Errors or runtime exceptions
- * thrown by the action are relayed to the caller.
+ * Performs the given action for each remaining element until all elements
+ * have been processed or the action throws an exception. Actions are
+ * performed in the order of iteration, if that order is specified.
+ * Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
@@ -240,10 +241,10 @@
double nextDouble();
/**
- * Performs the given action for each remaining element, in the order
- * elements occur when iterating, until all elements have been processed
- * or the action throws an exception. Errors or runtime exceptions
- * thrown by the action are relayed to the caller.
+ * Performs the given action for each remaining element until all elements
+ * have been processed or the action throws an exception. Actions are
+ * performed in the order of iteration, if that order is specified.
+ * Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
diff --git a/src/share/classes/java/util/Properties.java b/src/share/classes/java/util/Properties.java
index 073c777..aba5fd1 100644
--- a/src/share/classes/java/util/Properties.java
+++ b/src/share/classes/java/util/Properties.java
@@ -244,7 +244,6 @@
* As an example, each of the following three lines specifies the key
* {@code "Truth"} and the associated element value
* {@code "Beauty"}:
- * <p>
* <pre>
* Truth = Beauty
* Truth:Beauty
@@ -252,14 +251,12 @@
* </pre>
* As another example, the following three lines specify a single
* property:
- * <p>
* <pre>
* fruits apple, banana, pear, \
* cantaloupe, watermelon, \
* kiwi, mango
* </pre>
* The key is {@code "fruits"} and the associated element is:
- * <p>
* <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre>
* Note that a space appears before each {@code \} so that a space
* will appear after each comma in the final result; the {@code \},
@@ -268,13 +265,11 @@
* characters.
* <p>
* As a third example, the line:
- * <p>
* <pre>cheeses
* </pre>
* specifies that the key is {@code "cheeses"} and the associated
- * element is the empty string {@code ""}.<p>
+ * element is the empty string {@code ""}.
* <p>
- *
* <a name="unicodeescapes"></a>
* Characters in keys and elements can be represented in escape
* sequences similar to those used for character and string literals
diff --git a/src/share/classes/java/util/PropertyPermission.java b/src/share/classes/java/util/PropertyPermission.java
index 7a7700a..a07874e 100644
--- a/src/share/classes/java/util/PropertyPermission.java
+++ b/src/share/classes/java/util/PropertyPermission.java
@@ -51,11 +51,10 @@
* signify a wildcard match. For example: "java.*" and "*" signify a wildcard
* match, while "*java" and "a*b" do not.
* <P>
- * <P>
* The actions to be granted are passed to the constructor in a string containing
* a list of one or more comma-separated keywords. The possible keywords are
* "read" and "write". Their meaning is defined as follows:
- * <P>
+ *
* <DL>
* <DT> read
* <DD> read permission. Allows <code>System.getProperty</code> to
@@ -166,11 +165,11 @@
* Checks if this PropertyPermission object "implies" the specified
* permission.
* <P>
- * More specifically, this method returns true if:<p>
+ * More specifically, this method returns true if:
* <ul>
- * <li> <i>p</i> is an instanceof PropertyPermission,<p>
+ * <li> <i>p</i> is an instanceof PropertyPermission,
* <li> <i>p</i>'s actions are a subset of this
- * object's actions, and <p>
+ * object's actions, and
* <li> <i>p</i>'s name is implied by this object's
* name. For example, "java.*" implies "java.home".
* </ul>
diff --git a/src/share/classes/java/util/Queue.java b/src/share/classes/java/util/Queue.java
index 4d345df..975ea45 100644
--- a/src/share/classes/java/util/Queue.java
+++ b/src/share/classes/java/util/Queue.java
@@ -47,7 +47,6 @@
* implementations; in most implementations, insert operations cannot
* fail.
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of Queue methods</caption>
* <tr>
diff --git a/src/share/classes/java/util/ResourceBundle.java b/src/share/classes/java/util/ResourceBundle.java
index c95a7dc..95948c5 100644
--- a/src/share/classes/java/util/ResourceBundle.java
+++ b/src/share/classes/java/util/ResourceBundle.java
@@ -1084,7 +1084,6 @@
* bundles. Conceptually, the bundle loading process with the given
* <code>control</code> is performed in the following steps.
*
- * <p>
* <ol>
* <li>This factory method looks up the resource bundle in the cache for
* the specified <code>baseName</code>, <code>targetLocale</code> and
diff --git a/src/share/classes/java/util/Scanner.java b/src/share/classes/java/util/Scanner.java
index 36be8e3..4fe100f 100644
--- a/src/share/classes/java/util/Scanner.java
+++ b/src/share/classes/java/util/Scanner.java
@@ -216,7 +216,6 @@
* are specified in terms of the following regular-expression grammar, where
* Rmax is the highest digit in the radix being used (for example, Rmax is 9 in base 10).
*
- * <p>
* <dl>
* <dt><i>NonAsciiDigit</i>:
* <dd>A non-ASCII character c for which
diff --git a/src/share/classes/java/util/Spliterator.java b/src/share/classes/java/util/Spliterator.java
index b78bad6..18cb082 100644
--- a/src/share/classes/java/util/Spliterator.java
+++ b/src/share/classes/java/util/Spliterator.java
@@ -613,6 +613,7 @@
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
+ @SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action);
/**
@@ -630,6 +631,7 @@
* @param action The action
* @throws NullPointerException if the specified action is null
*/
+ @SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
diff --git a/src/share/classes/java/util/TimeZone.java b/src/share/classes/java/util/TimeZone.java
index aebe685..9649793 100644
--- a/src/share/classes/java/util/TimeZone.java
+++ b/src/share/classes/java/util/TimeZone.java
@@ -544,7 +544,16 @@
* @since 1.8
*/
public ZoneId toZoneId() {
- return ZoneId.of(getID(), ZoneId.SHORT_IDS);
+ String id = getID();
+ if (ZoneInfoFile.useOldMapping() && id.length() == 3) {
+ if ("EST".equals(id))
+ return ZoneId.of("America/New_York");
+ if ("MST".equals(id))
+ return ZoneId.of("America/Denver");
+ if ("HST".equals(id))
+ return ZoneId.of("America/Honolulu");
+ }
+ return ZoneId.of(id, ZoneId.SHORT_IDS);
}
private static TimeZone getTimeZone(String ID, boolean fallback) {
@@ -597,7 +606,7 @@
* Otherwise, the method takes the following steps to determine the default
* time zone.
*
- * <p><ul>
+ * <ul>
* <li>Use the {@code user.timezone} property value as the default
* time zone ID if it's available.</li>
* <li>Detect the platform time zone ID. The source of the
diff --git a/src/share/classes/java/util/UUID.java b/src/share/classes/java/util/UUID.java
index b9be5a4..7232b9d 100644
--- a/src/share/classes/java/util/UUID.java
+++ b/src/share/classes/java/util/UUID.java
@@ -233,7 +233,7 @@
* number describes how this {@code UUID} was generated.
*
* The version number has the following meaning:
- * <p><ul>
+ * <ul>
* <li>1 Time-based UUID
* <li>2 DCE security UUID
* <li>3 Name-based UUID
@@ -252,7 +252,7 @@
* number describes the layout of the {@code UUID}.
*
* The variant number has the following meaning:
- * <p><ul>
+ * <ul>
* <li>0 Reserved for NCS backward compatibility
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>
* (Leach-Salz), used by this class
diff --git a/src/share/classes/java/util/concurrent/BlockingDeque.java b/src/share/classes/java/util/concurrent/BlockingDeque.java
index d98586a..0a26fa8 100644
--- a/src/share/classes/java/util/concurrent/BlockingDeque.java
+++ b/src/share/classes/java/util/concurrent/BlockingDeque.java
@@ -50,7 +50,6 @@
* and the fourth blocks for only a given maximum time limit before giving
* up. These methods are summarized in the following table:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of BlockingDeque methods</caption>
* <tr>
@@ -126,7 +125,6 @@
* {@code BlockingQueue} interface are precisely equivalent to
* {@code BlockingDeque} methods as indicated in the following table:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
* <tr>
diff --git a/src/share/classes/java/util/concurrent/BlockingQueue.java b/src/share/classes/java/util/concurrent/BlockingQueue.java
index 8eb3ce2..3d09707 100644
--- a/src/share/classes/java/util/concurrent/BlockingQueue.java
+++ b/src/share/classes/java/util/concurrent/BlockingQueue.java
@@ -53,7 +53,6 @@
* and the fourth blocks for only a given maximum time limit before giving
* up. These methods are summarized in the following table:
*
- * <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of BlockingQueue methods</caption>
* <tr>
diff --git a/src/share/classes/java/util/concurrent/ConcurrentMap.java b/src/share/classes/java/util/concurrent/ConcurrentMap.java
index 6c902fa..3cb1fe7 100644
--- a/src/share/classes/java/util/concurrent/ConcurrentMap.java
+++ b/src/share/classes/java/util/concurrent/ConcurrentMap.java
@@ -36,7 +36,9 @@
package java.util.concurrent;
import java.util.Map;
import java.util.Objects;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.Function;
/**
* A {@link java.util.Map} providing thread safety and atomicity
@@ -64,9 +66,13 @@
* {@inheritDoc}
*
* @implNote This implementation assumes that the ConcurrentMap cannot
- * contain null values and get() returning null unambiguously means the key
- * is absent. Implementations which support null values must override this
- * default implementation.
+ * contain null values and {@code get()} returning null unambiguously means
+ * the key is absent. Implementations which support null values
+ * <strong>must</strong> override this default implementation.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
*/
@Override
default V getOrDefault(Object key, V defaultValue) {
@@ -74,6 +80,41 @@
return ((v = get(key)) != null) ? v : defaultValue;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec The default implementation is equivalent to, for this
+ * {@code map}:
+ * <pre> {@code
+ * for ((Map.Entry<K, V> entry : map.entrySet())
+ * action.accept(entry.getKey(), entry.getValue());
+ * }</pre>
+ *
+ * @implNote The default implementation assumes that
+ * {@code IllegalStateException} thrown by {@code getKey()} or
+ * {@code getValue()} indicates that the entry has been removed and cannot
+ * be processed. Operation continues for subsequent entries.
+ *
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ default void forEach(BiConsumer<? super K, ? super V> action) {
+ Objects.requireNonNull(action);
+ for (Map.Entry<K, V> entry : entrySet()) {
+ K k;
+ V v;
+ try {
+ k = entry.getKey();
+ v = entry.getValue();
+ } catch(IllegalStateException ise) {
+ // this usually means the entry is no longer in the map.
+ continue;
+ }
+ action.accept(k, v);
+ }
+ }
+
/**
* If the specified key is not already associated
* with a value, associate it with the given value.
@@ -82,10 +123,14 @@
* if (!map.containsKey(key))
* return map.put(key, value);
* else
- * return map.get(key);}</pre>
+ * return map.get(key);
+ * }</pre>
*
* except that the action is performed atomically.
*
+ * @implNote This implementation intentionally re-abstracts the
+ * inappropriate default provided in {@code Map}.
+ *
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
@@ -102,7 +147,7 @@
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
*/
- V putIfAbsent(K key, V value);
+ V putIfAbsent(K key, V value);
/**
* Removes the entry for a key only if currently mapped to a given value.
@@ -112,10 +157,14 @@
* map.remove(key);
* return true;
* } else
- * return false;}</pre>
+ * return false;
+ * }</pre>
*
* except that the action is performed atomically.
*
+ * @implNote This implementation intentionally re-abstracts the
+ * inappropriate default provided in {@code Map}.
+ *
* @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key
* @return {@code true} if the value was removed
@@ -138,10 +187,14 @@
* map.put(key, newValue);
* return true;
* } else
- * return false;}</pre>
+ * return false;
+ * }</pre>
*
* except that the action is performed atomically.
*
+ * @implNote This implementation intentionally re-abstracts the
+ * inappropriate default provided in {@code Map}.
+ *
* @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
@@ -164,10 +217,14 @@
* if (map.containsKey(key)) {
* return map.put(key, value);
* } else
- * return null;}</pre>
+ * return null;
+ * }</pre>
*
* except that the action is performed atomically.
*
+ * @implNote This implementation intentionally re-abstracts the
+ * inappropriate default provided in {@code Map}.
+ *
* @param key key with which the specified value is associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
@@ -189,10 +246,30 @@
/**
* {@inheritDoc}
*
- * @implNote This implementation assumes that the ConcurrentMap cannot
- * contain null values and get() returning null unambiguously means the key
- * is absent. Implementations which support null values
- * <strong>must</strong> override this default implementation.
+ * @implSpec
+ * <p>The default implementation is equivalent to, for this {@code map}:
+ * <pre> {@code
+ * for ((Map.Entry<K, V> entry : map.entrySet())
+ * do {
+ * K k = entry.getKey();
+ * V v = entry.getValue();
+ * } while(!replace(k, v, function.apply(k, v)));
+ * }</pre>
+ *
+ * The default implementation may retry these steps when multiple
+ * threads attempt updates including potentially calling the function
+ * repeatedly for a given key.
+ *
+ * <p>This implementation assumes that the ConcurrentMap cannot contain null
+ * values and {@code get()} returning null unambiguously means the key is
+ * absent. Implementations which support null values <strong>must</strong>
+ * override this default implementation.
+ *
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ * @since 1.8
*/
@Override
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
@@ -200,11 +277,243 @@
forEach((k,v) -> {
while(!replace(k, v, function.apply(k, v))) {
// v changed or k is gone
- if( (v = get(k)) == null) {
+ if ( (v = get(k)) == null) {
// k is no longer in the map.
break;
}
}
});
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec
+ * The default implementation is equivalent to the following steps for this
+ * {@code map}, then returning the current value or {@code null} if now
+ * absent:
+ *
+ * <pre> {@code
+ * if (map.get(key) == null) {
+ * V newValue = mappingFunction.apply(key);
+ * if (newValue != null)
+ * return map.putIfAbsent(key, newValue);
+ * }
+ * }</pre>
+ *
+ * The default implementation may retry these steps when multiple
+ * threads attempt updates including potentially calling the mapping
+ * function multiple times.
+ *
+ * <p>This implementation assumes that the ConcurrentMap cannot contain null
+ * values and {@code get()} returning null unambiguously means the key is
+ * absent. Implementations which support null values <strong>must</strong>
+ * override this default implementation.
+ *
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ default V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
+ V v, newValue;
+ return ((v = get(key)) == null &&
+ (newValue = mappingFunction.apply(key)) != null &&
+ (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the following
+ * steps for this {@code map}, then returning the current value or
+ * {@code null} if now absent. :
+ *
+ * <pre> {@code
+ * if (map.get(key) != null) {
+ * V oldValue = map.get(key);
+ * V newValue = remappingFunction.apply(key, oldValue);
+ * if (newValue != null)
+ * map.replace(key, oldValue, newValue);
+ * else
+ * map.remove(key, oldValue);
+ * }
+ * }</pre>
+ *
+ * The default implementation may retry these steps when multiple threads
+ * attempt updates including potentially calling the remapping function
+ * multiple times.
+ *
+ * <p>This implementation assumes that the ConcurrentMap cannot contain null
+ * values and {@code get()} returning null unambiguously means the key is
+ * absent. Implementations which support null values <strong>must</strong>
+ * override this default implementation.
+ *
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ default V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+ V oldValue;
+ while((oldValue = get(key)) != null) {
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (newValue != null) {
+ if (replace(key, oldValue, newValue))
+ return newValue;
+ } else if (remove(key, oldValue))
+ return null;
+ }
+ return oldValue;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the following
+ * steps for this {@code map}, then returning the current value or
+ * {@code null} if absent:
+ *
+ * <pre> {@code
+ * V oldValue = map.get(key);
+ * V newValue = remappingFunction.apply(key, oldValue);
+ * if (oldValue != null ) {
+ * if (newValue != null)
+ * map.replace(key, oldValue, newValue);
+ * else
+ * map.remove(key, oldValue);
+ * } else {
+ * if (newValue != null)
+ * map.putIfAbsent(key, newValue);
+ * else
+ * return null;
+ * }
+ * }</pre>
+ *
+ * The default implementation may retry these steps when multiple
+ * threads attempt updates including potentially calling the remapping
+ * function multiple times.
+ *
+ * <p>This implementation assumes that the ConcurrentMap cannot contain null
+ * values and {@code get()} returning null unambiguously means the key is
+ * absent. Implementations which support null values <strong>must</strong>
+ * override this default implementation.
+ *
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ default V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+ V oldValue = get(key);
+ for(;;) {
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (newValue == null) {
+ // delete mapping
+ if (oldValue != null || containsKey(key)) {
+ // something to remove
+ if (remove(key, oldValue)) {
+ // removed the old value as expected
+ return null;
+ }
+
+ // some other value replaced old value. try again.
+ oldValue = get(key);
+ } else {
+ // nothing to do. Leave things as they were.
+ return null;
+ }
+ } else {
+ // add or replace old mapping
+ if (oldValue != null) {
+ // replace
+ if (replace(key, oldValue, newValue)) {
+ // replaced as expected.
+ return newValue;
+ }
+
+ // some other value replaced old value. try again.
+ oldValue = get(key);
+ } else {
+ // add (replace if oldValue was null)
+ if ((oldValue = putIfAbsent(key, newValue)) == null) {
+ // replaced
+ return newValue;
+ }
+
+ // some other value replaced old value. try again.
+ }
+ }
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the
+ * following steps for this {@code map}, then returning the
+ * current value or {@code null} if absent:
+ *
+ * <pre> {@code
+ * V oldValue = map.get(key);
+ * V newValue = (oldValue == null) ? value :
+ * remappingFunction.apply(oldValue, value);
+ * if (newValue == null)
+ * map.remove(key);
+ * else if (oldValue == null)
+ * map.remove(key);
+ * else
+ * map.put(key, newValue);
+ * }</pre>
+ *
+ * <p>The default implementation may retry these steps when multiple
+ * threads attempt updates including potentially calling the remapping
+ * function multiple times.
+ *
+ * <p>This implementation assumes that the ConcurrentMap cannot contain null
+ * values and {@code get()} returning null unambiguously means the key is
+ * absent. Implementations which support null values <strong>must</strong>
+ * override this default implementation.
+ *
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ default V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+ Objects.requireNonNull(value);
+ V oldValue = get(key);
+ for (;;) {
+ if (oldValue != null) {
+ V newValue = remappingFunction.apply(oldValue, value);
+ if (newValue != null) {
+ if (replace(key, oldValue, newValue))
+ return newValue;
+ } else if (remove(key, oldValue)) {
+ return null;
+ }
+ oldValue = get(key);
+ } else {
+ if ((oldValue = putIfAbsent(key, value)) == null) {
+ return value;
+ }
+ }
+ }
+ }
}
diff --git a/src/share/classes/java/util/concurrent/Future.java b/src/share/classes/java/util/concurrent/Future.java
index 5c5578e..1011972 100644
--- a/src/share/classes/java/util/concurrent/Future.java
+++ b/src/share/classes/java/util/concurrent/Future.java
@@ -52,8 +52,8 @@
*
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
- * made-up.) <p>
- * <pre> {@code
+ * made-up.)
+ * <pre> {@code
* interface ArchiveSearcher { String search(String target); }
* class App {
* ExecutorService executor = ...
diff --git a/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
index 841f647..929818d 100644
--- a/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -224,18 +224,71 @@
return (float)get();
}
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- s.writeDouble(get());
+ /**
+ * Serialization proxy, used to avoid reference to the non-public
+ * Striped64 superclass in serialized forms.
+ * @serial include
+ */
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 7249069246863182397L;
+
+ /**
+ * The current value returned by get().
+ * @serial
+ */
+ private final double value;
+ /**
+ * The function used for updates.
+ * @serial
+ */
+ private final DoubleBinaryOperator function;
+ /**
+ * The identity value
+ * @serial
+ */
+ private final long identity;
+
+ SerializationProxy(DoubleAccumulator a) {
+ function = a.function;
+ identity = a.identity;
+ value = a.get();
+ }
+
+ /**
+ * Returns a {@code DoubleAccumulator} object with initial state
+ * held by this proxy.
+ *
+ * @return a {@code DoubleAccumulator} object with initial state
+ * held by this proxy.
+ */
+ private Object readResolve() {
+ double d = Double.longBitsToDouble(identity);
+ DoubleAccumulator a = new DoubleAccumulator(function, d);
+ a.base = Double.doubleToRawLongBits(value);
+ return a;
+ }
}
+ /**
+ * Returns a
+ * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
+ * SerializationProxy</a>
+ * representing the state of this instance.
+ *
+ * @return a {@link SerializationProxy}
+ * representing the state of this instance
+ */
+ private Object writeReplace() {
+ return new SerializationProxy(this);
+ }
+
+ /**
+ * @param s the stream
+ * @throws java.io.InvalidObjectException always
+ */
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
- cellsBusy = 0;
- cells = null;
- base = Double.doubleToRawLongBits(s.readDouble());
+ throws java.io.InvalidObjectException {
+ throw new java.io.InvalidObjectException("Proxy required");
}
}
diff --git a/src/share/classes/java/util/concurrent/atomic/DoubleAdder.java b/src/share/classes/java/util/concurrent/atomic/DoubleAdder.java
index 2db7ca8..f548d21 100644
--- a/src/share/classes/java/util/concurrent/atomic/DoubleAdder.java
+++ b/src/share/classes/java/util/concurrent/atomic/DoubleAdder.java
@@ -210,18 +210,58 @@
return (float)sum();
}
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- s.writeDouble(sum());
+ /**
+ * Serialization proxy, used to avoid reference to the non-public
+ * Striped64 superclass in serialized forms.
+ * @serial include
+ */
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 7249069246863182397L;
+
+ /**
+ * The current value returned by sum().
+ * @serial
+ */
+ private final double value;
+
+ SerializationProxy(DoubleAdder a) {
+ value = a.sum();
+ }
+
+ /**
+ * Returns a {@code DoubleAdder} object with initial state
+ * held by this proxy.
+ *
+ * @return a {@code DoubleAdder} object with initial state
+ * held by this proxy.
+ */
+ private Object readResolve() {
+ DoubleAdder a = new DoubleAdder();
+ a.base = Double.doubleToRawLongBits(value);
+ return a;
+ }
}
+ /**
+ * Returns a
+ * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAdder.SerializationProxy">
+ * SerializationProxy</a>
+ * representing the state of this instance.
+ *
+ * @return a {@link SerializationProxy}
+ * representing the state of this instance
+ */
+ private Object writeReplace() {
+ return new SerializationProxy(this);
+ }
+
+ /**
+ * @param s the stream
+ * @throws java.io.InvalidObjectException always
+ */
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
- cellsBusy = 0;
- cells = null;
- base = Double.doubleToRawLongBits(s.readDouble());
+ throws java.io.InvalidObjectException {
+ throw new java.io.InvalidObjectException("Proxy required");
}
}
diff --git a/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java
index 1289e6b..435aa1b 100644
--- a/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+++ b/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java
@@ -221,18 +221,70 @@
return (double)get();
}
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- s.writeLong(get());
+ /**
+ * Serialization proxy, used to avoid reference to the non-public
+ * Striped64 superclass in serialized forms.
+ * @serial include
+ */
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 7249069246863182397L;
+
+ /**
+ * The current value returned by get().
+ * @serial
+ */
+ private final long value;
+ /**
+ * The function used for updates.
+ * @serial
+ */
+ private final LongBinaryOperator function;
+ /**
+ * The identity value
+ * @serial
+ */
+ private final long identity;
+
+ SerializationProxy(LongAccumulator a) {
+ function = a.function;
+ identity = a.identity;
+ value = a.get();
+ }
+
+ /**
+ * Returns a {@code LongAccumulator} object with initial state
+ * held by this proxy.
+ *
+ * @return a {@code LongAccumulator} object with initial state
+ * held by this proxy.
+ */
+ private Object readResolve() {
+ LongAccumulator a = new LongAccumulator(function, identity);
+ a.base = value;
+ return a;
+ }
}
+ /**
+ * Returns a
+ * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAccumulator.SerializationProxy">
+ * SerializationProxy</a>
+ * representing the state of this instance.
+ *
+ * @return a {@link SerializationProxy}
+ * representing the state of this instance
+ */
+ private Object writeReplace() {
+ return new SerializationProxy(this);
+ }
+
+ /**
+ * @param s the stream
+ * @throws java.io.InvalidObjectException always
+ */
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
- cellsBusy = 0;
- cells = null;
- base = s.readLong();
+ throws java.io.InvalidObjectException {
+ throw new java.io.InvalidObjectException("Proxy required");
}
}
diff --git a/src/share/classes/java/util/concurrent/atomic/LongAdder.java b/src/share/classes/java/util/concurrent/atomic/LongAdder.java
index 70c5bed..e7415de 100644
--- a/src/share/classes/java/util/concurrent/atomic/LongAdder.java
+++ b/src/share/classes/java/util/concurrent/atomic/LongAdder.java
@@ -211,18 +211,58 @@
return (double)sum();
}
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- s.writeLong(sum());
+ /**
+ * Serialization proxy, used to avoid reference to the non-public
+ * Striped64 superclass in serialized forms.
+ * @serial include
+ */
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 7249069246863182397L;
+
+ /**
+ * The current value returned by sum().
+ * @serial
+ */
+ private final long value;
+
+ SerializationProxy(LongAdder a) {
+ value = a.sum();
+ }
+
+ /**
+ * Return a {@code LongAdder} object with initial state
+ * held by this proxy.
+ *
+ * @return a {@code LongAdder} object with initial state
+ * held by this proxy.
+ */
+ private Object readResolve() {
+ LongAdder a = new LongAdder();
+ a.base = value;
+ return a;
+ }
}
+ /**
+ * Returns a
+ * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAdder.SerializationProxy">
+ * SerializationProxy</a>
+ * representing the state of this instance.
+ *
+ * @return a {@link SerializationProxy}
+ * representing the state of this instance
+ */
+ private Object writeReplace() {
+ return new SerializationProxy(this);
+ }
+
+ /**
+ * @param s the stream
+ * @throws java.io.InvalidObjectException always
+ */
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
- cellsBusy = 0;
- cells = null;
- base = s.readLong();
+ throws java.io.InvalidObjectException {
+ throw new java.io.InvalidObjectException("Proxy required");
}
}
diff --git a/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 519477e..dc811c2 100644
--- a/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -56,7 +56,6 @@
* constraints. A nonfair lock that is continuously contended may
* indefinitely postpone one or more reader or writer threads, but
* will normally have higher throughput than a fair lock.
- * <p>
*
* <dt><b><i>Fair mode</i></b>
* <dd>When constructed as fair, threads contend for entry using an
diff --git a/src/share/classes/java/util/function/package-info.java b/src/share/classes/java/util/function/package-info.java
index f437f94..ccb329c 100644
--- a/src/share/classes/java/util/function/package-info.java
+++ b/src/share/classes/java/util/function/package-info.java
@@ -60,7 +60,11 @@
* actions, or predicates. In documenting functional interfaces, or referring
* to variables typed as functional interfaces, it is common to refer directly
* to those abstract concepts, for example using "this function" instead of
- * "the function represented by this object".
+ * "the function represented by this object". When an API method is said to
+ * accept or return a functional interface in this manner, such as "applies the
+ * provided function to...", this is understood to mean a <i>non-null</i>
+ * reference to an object implementing the appropriate functional interface,
+ * unless potential nullity is explicitly specified.
*
* <p>The functional interfaces in this package follow an extensible naming
* convention, as follows:
diff --git a/src/share/classes/java/util/jar/Pack200.java b/src/share/classes/java/util/jar/Pack200.java
index cf4fb98..5422431 100644
--- a/src/share/classes/java/util/jar/Pack200.java
+++ b/src/share/classes/java/util/jar/Pack200.java
@@ -44,7 +44,7 @@
* The unpacker engine is used by deployment applications to
* transform the byte-stream back to JAR format.
* <p>
- * Here is an example using packer and unpacker:<p>
+ * Here is an example using packer and unpacker:
* <pre>{@code
* import java.util.jar.Pack200;
* import java.util.jar.Pack200.*;
diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java
index 8596cbe..9a5e951 100644
--- a/src/share/classes/java/util/logging/LogManager.java
+++ b/src/share/classes/java/util/logging/LogManager.java
@@ -770,9 +770,10 @@
ref = owner.new LoggerWeakRef(logger);
namedLoggers.put(name, ref);
- // Apply any initial level defined for the new logger.
+ // Apply any initial level defined for the new logger, unless
+ // the logger's level is already initialized
Level level = owner.getLevelProperty(name + ".level", null);
- if (level != null) {
+ if (level != null && !logger.isLevelInitialized()) {
doSetLevel(logger, level);
}
diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java
index d673917..efc18c5 100644
--- a/src/share/classes/java/util/logging/Logger.java
+++ b/src/share/classes/java/util/logging/Logger.java
@@ -150,7 +150,7 @@
* has or inherited a resource bundle name, then that resource bundle name
* will be mapped to a {@code ResourceBundle} object, using the default Locale
* at the time of logging.
- * <br><a name="ResourceBundleMapping"/>When mapping resource bundle names to
+ * <br id="ResourceBundleMapping">When mapping resource bundle names to
* {@code ResourceBundle} objects, the logger will first try to use the
* Thread's {@linkplain java.lang.Thread#getContextClassLoader() context class
* loader} to map the given resource bundle name to a {@code ResourceBundle}.
@@ -555,7 +555,9 @@
* Even although the new logger is anonymous, it is configured
* to have the root logger ("") as its parent. This means that
* by default it inherits its effective level and handlers
- * from the root logger.
+ * from the root logger. Changing its parent via the
+ * {@link #setParent(java.util.logging.Logger) setParent} method
+ * will still require the security permission specified by that method.
* <p>
*
* @return a newly created private Logger
@@ -579,7 +581,9 @@
* Even although the new logger is anonymous, it is configured
* to have the root logger ("") as its parent. This means that
* by default it inherits its effective level and handlers
- * from the root logger.
+ * from the root logger. Changing its parent via the
+ * {@link #setParent(java.util.logging.Logger) setParent} method
+ * will still require the security permission specified by that method.
* <p>
* @param resourceBundleName name of ResourceBundle to be used for localizing
* messages for this logger.
@@ -648,8 +652,9 @@
* be published.
*
* @param newFilter a filter object (may be null)
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
*/
public void setFilter(Filter newFilter) throws SecurityException {
checkPermission();
@@ -1629,8 +1634,9 @@
* (non-null) level value.
*
* @param newLevel the new value for the log level (may be null)
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
*/
public void setLevel(Level newLevel) throws SecurityException {
checkPermission();
@@ -1640,6 +1646,10 @@
}
}
+ final boolean isLevelInitialized() {
+ return levelObject != null;
+ }
+
/**
* Get the log Level that has been specified for this Logger.
* The result may be null, which means that this logger's
@@ -1682,8 +1692,9 @@
* that essentially act as default handlers for all loggers.
*
* @param handler a logging Handler
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
*/
public void addHandler(Handler handler) throws SecurityException {
// Check for null handler
@@ -1698,8 +1709,9 @@
* Returns silently if the given Handler is not found or is null
*
* @param handler a logging Handler
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
*/
public void removeHandler(Handler handler) throws SecurityException {
checkPermission();
@@ -1726,8 +1738,9 @@
*
* @param useParentHandlers true if output is to be sent to the
* logger's parent.
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
*/
public void setUseParentHandlers(boolean useParentHandlers) {
checkPermission();
@@ -1890,8 +1903,9 @@
* {@linkplain ResourceBundle#getBaseBundleName base name},
* or if this logger already has a resource bundle set but
* the given bundle has a different base name.
- * @throws SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists,
+ * this logger is not anonymous, and the caller
+ * does not have LoggingPermission("control").
* @since 1.8
*/
public void setResourceBundle(ResourceBundle bundle) {
@@ -1948,14 +1962,20 @@
* It should not be called from application code.
* <p>
* @param parent the new parent logger
- * @exception SecurityException if a security manager exists and if
- * the caller does not have LoggingPermission("control").
+ * @throws SecurityException if a security manager exists and if
+ * the caller does not have LoggingPermission("control").
*/
public void setParent(Logger parent) {
if (parent == null) {
throw new NullPointerException();
}
- checkPermission();
+
+ // check permission for all loggers, including anonymous loggers
+ if (manager == null) {
+ manager = LogManager.getLogManager();
+ }
+ manager.checkPermission();
+
doSetParent(parent);
}
diff --git a/src/share/classes/java/util/regex/Pattern.java b/src/share/classes/java/util/regex/Pattern.java
index 21a0029..e9a0c67 100644
--- a/src/share/classes/java/util/regex/Pattern.java
+++ b/src/share/classes/java/util/regex/Pattern.java
@@ -618,7 +618,7 @@
* are in conformance with the recommendation of <i>Annex C: Compatibility Properties</i>
* of <a href="http://www.unicode.org/reports/tr18/"><i>Unicode Regular Expression
* </i></a>, when {@link #UNICODE_CHARACTER_CLASS} flag is specified.
- * <p>
+ *
* <table border="0" cellpadding="1" cellspacing="0"
* summary="predefined and posix character classes in Unicode mode">
* <tr align="left">
diff --git a/src/share/classes/java/util/spi/LocaleServiceProvider.java b/src/share/classes/java/util/spi/LocaleServiceProvider.java
index 87af978..128e40f 100644
--- a/src/share/classes/java/util/spi/LocaleServiceProvider.java
+++ b/src/share/classes/java/util/spi/LocaleServiceProvider.java
@@ -41,7 +41,7 @@
* <code>java.util</code> packages use implementations of the provider
* interfaces to offer support for locales beyond the set of locales
* supported by the Java runtime environment itself.
- * <p>
+ *
* <h3>Packaging of Locale Sensitive Service Provider Implementations</h3>
* Implementations of these locale sensitive services are packaged using the
* <a href="../../../../technotes/guides/extensions/index.html">Java Extension Mechanism</a>
diff --git a/src/share/classes/java/util/stream/BaseStream.java b/src/share/classes/java/util/stream/BaseStream.java
index 4b7006b..35d46e0 100644
--- a/src/share/classes/java/util/stream/BaseStream.java
+++ b/src/share/classes/java/util/stream/BaseStream.java
@@ -35,9 +35,10 @@
import java.util.function.Predicate;
/**
- * A sequence of elements supporting sequential and parallel aggregate
- * operations. The following example illustrates an aggregate operation using
- * {@link Stream} and {@link IntStream}:
+ * Base interface for streams, which are sequences of elements supporting
+ * sequential and parallel aggregate operations. The following example
+ * illustrates an aggregate operation using the stream types {@link Stream}
+ * and {@link IntStream}, computing the sum of the weights of the red widgets:
*
* <pre>{@code
* int sum = widgets.stream()
@@ -46,80 +47,18 @@
* .sum();
* }</pre>
*
- * In this example, {@code widgets} is a {@code Collection<Widget>}. We create
- * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
- * filter it to produce a stream containing only the red widgets, and then
- * transform it into a stream of {@code int} values representing the weight of
- * each red widget. Then this stream is summed to produce a total weight.
- *
- * <p>To perform a computation, stream
- * <a href="package-summary.html#StreamOps">operations</a> are composed into a
- * <em>stream pipeline</em>. A stream pipeline consists of a source (which
- * might be an array, a collection, a generator function, an IO channel,
- * etc), zero or more <em>intermediate operations</em> (which transform a
- * stream into another stream, such as {@link Stream#filter(Predicate)}), and a
- * <em>terminal operation</em> (which produces a result or side-effect, such
- * as {@link IntStream#sum()} or {@link IntStream#forEach(IntConsumer)}).
- * Streams are lazy; computation on the source data is only performed when the
- * terminal operation is initiated, and source elements are consumed only
- * as needed.
- *
- * <p>Collections and streams, while bearing some superficial similarities,
- * have different goals. Collections are primarily concerned with the efficient
- * management of, and access to, their elements. By contrast, streams do not
- * provide a means to directly access or manipulate their elements, and are
- * instead concerned with declaratively describing their source and the
- * computational operations which will be performed in aggregate on that source.
- * However, if the provided stream operations do not offer the desired
- * functionality, the {@link #iterator()} and {@link #spliterator()} operations
- * can be used to perform a controlled traversal.
- *
- * <p>A stream pipeline, like the "widgets" example above, can be viewed as
- * a <em>query</em> on the stream source. Unless the source was explicitly
- * designed for concurrent modification (such as a {@link ConcurrentHashMap}),
- * unpredictable or erroneous behavior may result from modifying the stream
- * source while it is being queried.
- *
- * <p>Most stream operations accept parameters that describe user-specified
- * behavior, such as the lambda expression {@code w -> w.getWeight()} passed to
- * {@code mapToInt} in the example above. Such parameters are always instances
- * of a <a href="../function/package-summary.html">functional interface</a> such
- * as {@link java.util.function.Function}, and are often lambda expressions or
- * method references. These parameters can never be null, should not modify the
- * stream source, and should be
- * <a href="package-summary.html#NonInterference">effectively stateless</a>
- * (their result should not depend on any state that might change during
- * execution of the stream pipeline.)
- *
- * <p>A stream should be operated on (invoking an intermediate or terminal stream
- * operation) only once. This rules out, for example, "forked" streams, where
- * the same source feeds two or more pipelines, or multiple traversals of the
- * same stream. A stream implementation may throw {@link IllegalStateException}
- * if it detects that the stream is being reused. However, since some stream
- * operations may return their receiver rather than a new stream object, it may
- * not be possible to detect reuse in all cases.
- *
- * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
- * but nearly all stream instances do not actually need to be closed after use.
- * Generally, only streams whose source is an IO channel (such as those returned
- * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
- * are backed by collections, arrays, or generating functions, which require no
- * special resource management. (If a stream does require closing, it can be
- * declared as a resource in a {@code try}-with-resources statement.)
- *
- * <p>Stream pipelines may execute either sequentially or in
- * <a href="package-summary.html#Parallelism">parallel</a>. This
- * execution mode is a property of the stream. Streams are created
- * with an initial choice of sequential or parallel execution. (For example,
- * {@link Collection#stream() Collection.stream()} creates a sequential stream,
- * and {@link Collection#parallelStream() Collection.parallelStream()} creates
- * a parallel one.) This choice of execution mode may be modified by the
- * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
- * the {@link #isParallel()} method.
+ * See the class documentation for {@link Stream} and the package documentation
+ * for <a href="package-summary.html">java.util.stream</a> for additional
+ * specification of streams, stream operations, stream pipelines, and
+ * parallelism, which governs the behavior of all stream types.
*
* @param <T> the type of the stream elements
* @param <S> the type of of the stream implementing {@code BaseStream}
* @since 1.8
+ * @see Stream
+ * @see IntStream
+ * @see LongStream
+ * @see DoubleStream
* @see <a href="package-summary.html">java.util.stream</a>
*/
public interface BaseStream<T, S extends BaseStream<T, S>>
diff --git a/src/share/classes/java/util/stream/Collectors.java b/src/share/classes/java/util/stream/Collectors.java
index 00f7c86..93ffb01 100644
--- a/src/share/classes/java/util/stream/Collectors.java
+++ b/src/share/classes/java/util/stream/Collectors.java
@@ -462,7 +462,7 @@
*/
public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) {
- return new CollectorImpl<T, int[], Integer>(
+ return new CollectorImpl<>(
() -> new int[1],
(a, t) -> { a[0] += mapper.applyAsInt(t); },
(a, b) -> { a[0] += b[0]; return a; },
@@ -480,7 +480,7 @@
*/
public static <T> Collector<T, ?, Long>
summingLong(ToLongFunction<? super T> mapper) {
- return new CollectorImpl<T, long[], Long>(
+ return new CollectorImpl<>(
() -> new long[1],
(a, t) -> { a[0] += mapper.applyAsLong(t); },
(a, b) -> { a[0] += b[0]; return a; },
@@ -505,7 +505,7 @@
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
- return new CollectorImpl<T, double[], Double>(
+ return new CollectorImpl<>(
() -> new double[1],
(a, t) -> { a[0] += mapper.applyAsDouble(t); },
(a, b) -> { a[0] += b[0]; return a; },
@@ -523,7 +523,7 @@
*/
public static <T> Collector<T, ?, Double>
averagingInt(ToIntFunction<? super T> mapper) {
- return new CollectorImpl<T, long[], Double>(
+ return new CollectorImpl<>(
() -> new long[2],
(a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
@@ -541,7 +541,7 @@
*/
public static <T> Collector<T, ?, Double>
averagingLong(ToLongFunction<? super T> mapper) {
- return new CollectorImpl<T, long[], Double>(
+ return new CollectorImpl<>(
() -> new long[2],
(a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
@@ -566,7 +566,7 @@
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
- return new CollectorImpl<T, double[], Double>(
+ return new CollectorImpl<>(
() -> new double[2],
(a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
@@ -723,6 +723,14 @@
* groupingBy(classifier, toList());
* }</pre>
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If
+ * preservation of the order in which elements appear in the resulting {@code Map}
+ * collector is not required, using {@link #groupingByConcurrent(Function)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the type of the keys
* @param classifier the classifier function mapping input elements to keys
@@ -759,6 +767,14 @@
* mapping(Person::getLastName, toSet())));
* }</pre>
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If
+ * preservation of the order in which elements are presented to the downstream
+ * collector is not required, using {@link #groupingByConcurrent(Function, Collector)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the type of the keys
* @param <A> the intermediate accumulation type of the downstream collector
@@ -798,6 +814,14 @@
* mapping(Person::getLastName, toSet())));
* }</pre>
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If
+ * preservation of the order in which elements are presented to the downstream
+ * collector is not required, using {@link #groupingByConcurrent(Function, Supplier, Collector)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the type of the keys
* @param <A> the intermediate accumulation type of the downstream collector
@@ -871,7 +895,7 @@
* @param <T> the type of the input elements
* @param <K> the type of the keys
* @param classifier a classifier function mapping input elements to keys
- * @return a {@code Collector} implementing the group-by operation
+ * @return a concurrent, unordered {@code Collector} implementing the group-by operation
*
* @see #groupingBy(Function)
* @see #groupingByConcurrent(Function, Collector)
@@ -912,7 +936,7 @@
* @param <D> the result type of the downstream reduction
* @param classifier a classifier function mapping input elements to keys
* @param downstream a {@code Collector} implementing the downstream reduction
- * @return a {@code Collector} implementing the cascaded group-by operation
+ * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
*
* @see #groupingBy(Function, Collector)
* @see #groupingByConcurrent(Function)
@@ -958,7 +982,7 @@
* @param downstream a {@code Collector} implementing the downstream reduction
* @param mapFactory a function which, when called, produces a new empty
* {@code ConcurrentMap} of the desired type
- * @return a {@code Collector} implementing the cascaded group-by operation
+ * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
*
* @see #groupingByConcurrent(Function)
* @see #groupingByConcurrent(Function, Collector)
@@ -1072,7 +1096,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
@@ -1101,6 +1125,14 @@
* Functions.identity());
* }</pre>
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If it is
+ * not required that results are inserted into the {@code Map} in encounter
+ * order, using {@link #toConcurrentMap(Function, Function)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function
@@ -1121,7 +1153,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
@@ -1146,6 +1178,14 @@
* (s, a) -> s + ", " + a));
* }</pre>
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If it is
+ * not required that results are merged into the {@code Map} in encounter
+ * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function
@@ -1172,7 +1212,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
@@ -1182,6 +1222,14 @@
* results are merged using the provided merging function. The {@code Map}
* is created by a provided supplier function.
*
+ * @implNote
+ * The returned {@code Collector} is not concurrent. For parallel stream
+ * pipelines, the {@code combiner} function operates by merging the keys
+ * from one map into another, which can be an expensive operation. If it is
+ * not required that results are merged into the {@code Map} in encounter
+ * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
+ * may offer better parallel performance.
+ *
* @param <T> the type of the input elements
* @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function
@@ -1215,7 +1263,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements.
*
@@ -1252,7 +1300,7 @@
* @param <U> the output type of the value mapping function
* @param keyMapper the mapping function to produce keys
* @param valueMapper the mapping function to produce values
- * @return a concurrent {@code Collector} which collects elements into a
+ * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of
* applying a value mapping function to the input elements
@@ -1268,7 +1316,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements.
*
@@ -1303,7 +1351,7 @@
* @param mergeFunction a merge function, used to resolve collisions between
* values associated with the same key, as supplied
* to {@link Map#merge(Object, Object, BiFunction)}
- * @return a concurrent {@code Collector} which collects elements into a
+ * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of
* applying a value mapping function to all input elements equal to the key
@@ -1322,7 +1370,7 @@
}
/**
- * Returns a {@code Collector} that accumulate elements into a
+ * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements.
*
@@ -1345,7 +1393,7 @@
* to {@link Map#merge(Object, Object, BiFunction)}
* @param mapSupplier a function which returns a new, empty {@code Map} into
* which the results will be inserted
- * @return a concurrent {@code Collector} which collects elements into a
+ * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of
* applying a value mapping function to all input elements equal to the key
diff --git a/src/share/classes/java/util/stream/DistinctOps.java b/src/share/classes/java/util/stream/DistinctOps.java
index 1c4dfee..66d7cb7 100644
--- a/src/share/classes/java/util/stream/DistinctOps.java
+++ b/src/share/classes/java/util/stream/DistinctOps.java
@@ -54,6 +54,16 @@
static <T> ReferencePipeline<T, T> makeRef(AbstractPipeline<?, T, ?> upstream) {
return new ReferencePipeline.StatefulOp<T, T>(upstream, StreamShape.REFERENCE,
StreamOpFlag.IS_DISTINCT | StreamOpFlag.NOT_SIZED) {
+
+ <P_IN> Node<T> reduce(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) {
+ // If the stream is SORTED then it should also be ORDERED so the following will also
+ // preserve the sort order
+ TerminalOp<T, LinkedHashSet<T>> reduceOp
+ = ReduceOps.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::add,
+ LinkedHashSet::addAll);
+ return Nodes.node(reduceOp.evaluateParallel(helper, spliterator));
+ }
+
@Override
<P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator,
@@ -63,12 +73,7 @@
return helper.evaluate(spliterator, false, generator);
}
else if (StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) {
- // If the stream is SORTED then it should also be ORDERED so the following will also
- // preserve the sort order
- TerminalOp<T, LinkedHashSet<T>> reduceOp
- = ReduceOps.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::add,
- LinkedHashSet::addAll);
- return Nodes.node(reduceOp.evaluateParallel(helper, spliterator));
+ return reduce(helper, spliterator);
}
else {
// Holder of null state since ConcurrentHashMap does not support null values
@@ -95,6 +100,22 @@
}
@Override
+ <P_IN> Spliterator<T> opEvaluateParallelLazy(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) {
+ if (StreamOpFlag.DISTINCT.isKnown(helper.getStreamAndOpFlags())) {
+ // No-op
+ return helper.wrapSpliterator(spliterator);
+ }
+ else if (StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) {
+ // Not lazy, barrier required to preserve order
+ return reduce(helper, spliterator).spliterator();
+ }
+ else {
+ // Lazy
+ return new StreamSpliterators.DistinctSpliterator<>(helper.wrapSpliterator(spliterator));
+ }
+ }
+
+ @Override
Sink<T> opWrapSink(int flags, Sink<T> sink) {
Objects.requireNonNull(sink);
diff --git a/src/share/classes/java/util/stream/DoubleStream.java b/src/share/classes/java/util/stream/DoubleStream.java
index b50471d..68d792d 100644
--- a/src/share/classes/java/util/stream/DoubleStream.java
+++ b/src/share/classes/java/util/stream/DoubleStream.java
@@ -50,9 +50,13 @@
import java.util.function.Supplier;
/**
- * A sequence of elements supporting sequential and parallel aggregate
- * operations. The following example illustrates an aggregate operation using
- * {@link Stream} and {@link DoubleStream}:
+ * A sequence of primitive double-valued elements supporting sequential and parallel
+ * aggregate operations. This is the {@code double} primitive specialization of
+ * {@link Stream}.
+ *
+ * <p>The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link DoubleStream}, computing the sum of the weights of the
+ * red widgets:
*
* <pre>{@code
* double sum = widgets.stream()
@@ -61,78 +65,13 @@
* .sum();
* }</pre>
*
- * In this example, {@code widgets} is a {@code Collection<Widget>}. We create
- * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
- * filter it to produce a stream containing only the red widgets, and then
- * transform it into a stream of {@code double} values representing the weight of
- * each red widget. Then this stream is summed to produce a total weight.
- *
- * <p>To perform a computation, stream
- * <a href="package-summary.html#StreamOps">operations</a> are composed into a
- * <em>stream pipeline</em>. A stream pipeline consists of a source (which
- * might be an array, a collection, a generator function, an IO channel,
- * etc), zero or more <em>intermediate operations</em> (which transform a
- * stream into another stream, such as {@link DoubleStream#filter(DoublePredicate)}), and a
- * <em>terminal operation</em> (which produces a result or side-effect, such
- * as {@link DoubleStream#sum()} or {@link DoubleStream#forEach(DoubleConsumer)}.
- * Streams are lazy; computation on the source data is only performed when the
- * terminal operation is initiated, and source elements are consumed only
- * as needed.
- *
- * <p>Collections and streams, while bearing some superficial similarities,
- * have different goals. Collections are primarily concerned with the efficient
- * management of, and access to, their elements. By contrast, streams do not
- * provide a means to directly access or manipulate their elements, and are
- * instead concerned with declaratively describing their source and the
- * computational operations which will be performed in aggregate on that source.
- * However, if the provided stream operations do not offer the desired
- * functionality, the {@link #iterator()} and {@link #spliterator()} operations
- * can be used to perform a controlled traversal.
- *
- * <p>A stream pipeline, like the "widgets" example above, can be viewed as
- * a <em>query</em> on the stream source. Unless the source was explicitly
- * designed for concurrent modification (such as a {@link ConcurrentHashMap}),
- * unpredictable or erroneous behavior may result from modifying the stream
- * source while it is being queried.
- *
- * <p>Most stream operations accept parameters that describe user-specified
- * behavior, such as the lambda expression {@code w -> w.getWeight()} passed to
- * {@code mapToDouble} in the example above. Such parameters are always instances
- * of a <a href="../function/package-summary.html">functional interface</a> such
- * as {@link java.util.function.Function}, and are often lambda expressions or
- * method references. These parameters can never be null, should not modify the
- * stream source, and should be
- * <a href="package-summary.html#NonInterference">effectively stateless</a>
- * (their result should not depend on any state that might change during
- * execution of the stream pipeline.)
- *
- * <p>A stream should be operated on (invoking an intermediate or terminal stream
- * operation) only once. This rules out, for example, "forked" streams, where
- * the same source feeds two or more pipelines, or multiple traversals of the
- * same stream. A stream implementation may throw {@link IllegalStateException}
- * if it detects that the stream is being reused. However, since some stream
- * operations may return their receiver rather than a new stream object, it may
- * not be possible to detect reuse in all cases.
- *
- * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
- * but nearly all stream instances do not actually need to be closed after use.
- * Generally, only streams whose source is an IO channel (such as those returned
- * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
- * are backed by collections, arrays, or generating functions, which require no
- * special resource management. (If a stream does require closing, it can be
- * declared as a resource in a {@code try}-with-resources statement.)
- *
- * <p>Stream pipelines may execute either sequentially or in
- * <a href="package-summary.html#Parallelism">parallel</a>. This
- * execution mode is a property of the stream. Streams are created
- * with an initial choice of sequential or parallel execution. (For example,
- * {@link Collection#stream() Collection.stream()} creates a sequential stream,
- * and {@link Collection#parallelStream() Collection.parallelStream()} creates
- * a parallel one.) This choice of execution mode may be modified by the
- * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
- * the {@link #isParallel()} method.
+ * See the class documentation for {@link Stream} and the package documentation
+ * for <a href="package-summary.html">java.util.stream</a> for additional
+ * specification of streams, stream operations, stream pipelines, and
+ * parallelism.
*
* @since 1.8
+ * @see Stream
* @see <a href="package-summary.html">java.util.stream</a>
*/
public interface DoubleStream extends BaseStream<Double, DoubleStream> {
@@ -144,9 +83,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> predicate to apply to
- * each element to determine if it should be included
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to each element to determine if it
+ * should be included
* @return the new stream
*/
DoubleStream filter(DoublePredicate predicate);
@@ -158,9 +98,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to
- * each element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
DoubleStream map(DoubleUnaryOperator mapper);
@@ -173,9 +113,9 @@
* intermediate operation</a>.
*
* @param <U> the element type of the new stream
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
<U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper);
@@ -187,9 +127,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
IntStream mapToInt(DoubleToIntFunction mapper);
@@ -201,9 +141,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
LongStream mapToLong(DoubleToLongFunction mapper);
@@ -218,10 +158,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to
- * each element which produces an {@code DoubleStream} of new
- * values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a
+ * {@code DoubleStream} of new values
* @return the new stream
* @see Stream#flatMap(Function)
*/
@@ -276,8 +216,8 @@
* }</pre>
*
* @param action a <a href="package-summary.html#NonInterference">
- * non-interfering</a> action to perform on the elements as
- * they are consumed from the stream
+ * non-interfering</a> action to perform on the elements as
+ * they are consumed from the stream
* @return the new stream
*/
DoubleStream peek(DoubleConsumer action);
@@ -423,9 +363,10 @@
* synchronization and with greatly reduced risk of data races.
*
* @param identity the identity value for the accumulating function
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #sum()
* @see #min()
@@ -462,9 +403,10 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #reduce(double, DoubleBinaryOperator)
*/
@@ -495,14 +437,15 @@
* @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called
* multiple times and must return a fresh value each time.
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for incorporating an additional
- * element into a result
- * @param combiner an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values, which
- * must be compatible with the accumulator function
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for incorporating an additional element into a result
+ * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values, which must be
+ * compatible with the accumulator function
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@@ -544,8 +487,8 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @apiNote Sorting values by increasing absolute magnitude tends to yield
- * more accurate results.
+ * @apiNote Elements sorted by increasing absolute magnitude tend
+ * to yield more accurate results.
*
* @return the sum of elements in this stream
*/
@@ -651,48 +594,67 @@
/**
* Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not
- * necessary for determining the result.
+ * necessary for determining the result. If the stream is empty then
+ * {@code false} is returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
+ * @apiNote
+ * This method evaluates the <em>existential quantification</em> of the
+ * predicate over the elements of the stream (for some x P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided
- * predicate otherwise {@code false}
+ * predicate, otherwise {@code false}
*/
boolean anyMatch(DoublePredicate predicate);
/**
* Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if all elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * predicate over the elements of the stream (for all x P(x)). If the
+ * stream is empty, the quantification is said to be <em>vacuously
+ * satisfied</em> and is always {@code true} (regardless of P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either all elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean allMatch(DoublePredicate predicate);
/**
* Returns whether no elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if no elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * negated predicate over the elements of the stream (for all x ~P(x)). If
+ * the stream is empty, the quantification is said to be vacuously satisfied
+ * and is always {@code true}, regardless of P(x).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either no elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean noneMatch(DoublePredicate predicate);
@@ -832,12 +794,12 @@
}
/**
- * Returns a sequential stream where each element is generated by
- * the provided {@code DoubleSupplier}. This is suitable for generating
- * constant streams, streams of random elements, etc.
+ * Returns an infinite sequential unordered stream where each element is
+ * generated by the provided {@code DoubleSupplier}. This is suitable for
+ * generating constant streams, streams of random elements, etc.
*
* @param s the {@code DoubleSupplier} for generated elements
- * @return a new sequential {@code DoubleStream}
+ * @return a new infinite sequential unordered {@code DoubleStream}
*/
public static DoubleStream generate(DoubleSupplier s) {
Objects.requireNonNull(s);
@@ -848,11 +810,16 @@
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
- * second stream. The resulting stream is ordered if both
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * @implNote
+ * Use caution when constructing streams from repeated concatenation.
+ * Accessing an element of a deeply concatenated stream can result in deep
+ * call chains, or even {@code StackOverflowException}.
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
diff --git a/src/share/classes/java/util/stream/IntStream.java b/src/share/classes/java/util/stream/IntStream.java
index ae0eb49..b9fae57 100644
--- a/src/share/classes/java/util/stream/IntStream.java
+++ b/src/share/classes/java/util/stream/IntStream.java
@@ -24,11 +24,7 @@
*/
package java.util.stream;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.Arrays;
-import java.util.Collection;
import java.util.IntSummaryStatistics;
import java.util.Objects;
import java.util.OptionalDouble;
@@ -36,7 +32,6 @@
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
@@ -51,9 +46,13 @@
import java.util.function.Supplier;
/**
- * A sequence of elements supporting sequential and parallel aggregate
- * operations. The following example illustrates an aggregate operation using
- * {@link Stream} and {@link IntStream}:
+ * A sequence of primitive int-valued elements supporting sequential and parallel
+ * aggregate operations. This is the {@code int} primitive specialization of
+ * {@link Stream}.
+ *
+ * <p>The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link IntStream}, computing the sum of the weights of the
+ * red widgets:
*
* <pre>{@code
* int sum = widgets.stream()
@@ -62,78 +61,13 @@
* .sum();
* }</pre>
*
- * In this example, {@code widgets} is a {@code Collection<Widget>}. We create
- * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
- * filter it to produce a stream containing only the red widgets, and then
- * transform it into a stream of {@code int} values representing the weight of
- * each red widget. Then this stream is summed to produce a total weight.
- *
- * <p>To perform a computation, stream
- * <a href="package-summary.html#StreamOps">operations</a> are composed into a
- * <em>stream pipeline</em>. A stream pipeline consists of a source (which
- * might be an array, a collection, a generator function, an IO channel,
- * etc), zero or more <em>intermediate operations</em> (which transform a
- * stream into another stream, such as {@link IntStream#filter(IntPredicate)}), and a
- * <em>terminal operation</em> (which produces a result or side-effect, such
- * as {@link IntStream#sum()} or {@link IntStream#forEach(IntConsumer)}).
- * Streams are lazy; computation on the source data is only performed when the
- * terminal operation is initiated, and source elements are consumed only
- * as needed.
- *
- * <p>Collections and streams, while bearing some superficial similarities,
- * have different goals. Collections are primarily concerned with the efficient
- * management of, and access to, their elements. By contrast, streams do not
- * provide a means to directly access or manipulate their elements, and are
- * instead concerned with declaratively describing their source and the
- * computational operations which will be performed in aggregate on that source.
- * However, if the provided stream operations do not offer the desired
- * functionality, the {@link #iterator()} and {@link #spliterator()} operations
- * can be used to perform a controlled traversal.
- *
- * <p>A stream pipeline, like the "widgets" example above, can be viewed as
- * a <em>query</em> on the stream source. Unless the source was explicitly
- * designed for concurrent modification (such as a {@link ConcurrentHashMap}),
- * unpredictable or erroneous behavior may result from modifying the stream
- * source while it is being queried.
- *
- * <p>Most stream operations accept parameters that describe user-specified
- * behavior, such as the lambda expression {@code w -> w.getWeight()} passed to
- * {@code mapToInt} in the example above. Such parameters are always instances
- * of a <a href="../function/package-summary.html">functional interface</a> such
- * as {@link java.util.function.Function}, and are often lambda expressions or
- * method references. These parameters can never be null, should not modify the
- * stream source, and should be
- * <a href="package-summary.html#NonInterference">effectively stateless</a>
- * (their result should not depend on any state that might change during
- * execution of the stream pipeline.)
- *
- * <p>A stream should be operated on (invoking an intermediate or terminal stream
- * operation) only once. This rules out, for example, "forked" streams, where
- * the same source feeds two or more pipelines, or multiple traversals of the
- * same stream. A stream implementation may throw {@link IllegalStateException}
- * if it detects that the stream is being reused. However, since some stream
- * operations may return their receiver rather than a new stream object, it may
- * not be possible to detect reuse in all cases.
- *
- * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
- * but nearly all stream instances do not actually need to be closed after use.
- * Generally, only streams whose source is an IO channel (such as those returned
- * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
- * are backed by collections, arrays, or generating functions, which require no
- * special resource management. (If a stream does require closing, it can be
- * declared as a resource in a {@code try}-with-resources statement.)
- *
- * <p>Stream pipelines may execute either sequentially or in
- * <a href="package-summary.html#Parallelism">parallel</a>. This
- * execution mode is a property of the stream. Streams are created
- * with an initial choice of sequential or parallel execution. (For example,
- * {@link Collection#stream() Collection.stream()} creates a sequential stream,
- * and {@link Collection#parallelStream() Collection.parallelStream()} creates
- * a parallel one.) This choice of execution mode may be modified by the
- * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
- * the {@link #isParallel()} method.
+ * See the class documentation for {@link Stream} and the package documentation
+ * for <a href="package-summary.html">java.util.stream</a> for additional
+ * specification of streams, stream operations, stream pipelines, and
+ * parallelism.
*
* @since 1.8
+ * @see Stream
* @see <a href="package-summary.html">java.util.stream</a>
*/
public interface IntStream extends BaseStream<Integer, IntStream> {
@@ -145,9 +79,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> predicate to apply to
- * each element to determine if it should be included
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to each element to determine if it
+ * should be included
* @return the new stream
*/
IntStream filter(IntPredicate predicate);
@@ -159,9 +94,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
IntStream map(IntUnaryOperator mapper);
@@ -174,9 +109,9 @@
* intermediate operation</a>.
*
* @param <U> the element type of the new stream
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper);
@@ -188,9 +123,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
LongStream mapToLong(IntToLongFunction mapper);
@@ -202,9 +137,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
DoubleStream mapToDouble(IntToDoubleFunction mapper);
@@ -219,10 +154,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to
- * each element which produces an {@code IntStream} of new
- * values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces an
+ * {@code IntStream} of new values
* @return the new stream
* @see Stream#flatMap(Function)
*/
@@ -421,9 +356,10 @@
* synchronization and with greatly reduced risk of data races.
*
* @param identity the identity value for the accumulating function
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #sum()
* @see #min()
@@ -460,9 +396,10 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #reduce(int, IntBinaryOperator)
*/
@@ -492,14 +429,15 @@
* @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called
* multiple times and must return a fresh value each time.
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for incorporating an additional
- * element into a result
- * @param combiner an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values, which
- * must be compatible with the accumulator function
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for incorporating an additional element into a result
+ * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values, which must be
+ * compatible with the accumulator function
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@@ -599,48 +537,67 @@
/**
* Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not
- * necessary for determining the result.
+ * necessary for determining the result. If the stream is empty then
+ * {@code false} is returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
+ * @apiNote
+ * This method evaluates the <em>existential quantification</em> of the
+ * predicate over the elements of the stream (for some x P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided
- * predicate otherwise {@code false}
+ * predicate, otherwise {@code false}
*/
boolean anyMatch(IntPredicate predicate);
/**
* Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if all elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * predicate over the elements of the stream (for all x P(x)). If the
+ * stream is empty, the quantification is said to be <em>vacuously
+ * satisfied</em> and is always {@code true} (regardless of P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either all elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean allMatch(IntPredicate predicate);
/**
* Returns whether no elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if no elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * negated predicate over the elements of the stream (for all x ~P(x)). If
+ * the stream is empty, the quantification is said to be vacuously satisfied
+ * and is always {@code true}, regardless of P(x).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either no elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean noneMatch(IntPredicate predicate);
@@ -803,12 +760,12 @@
}
/**
- * Returns a sequential stream where each element is generated by
- * the provided {@code IntSupplier}. This is suitable for generating
- * constant streams, streams of random elements, etc.
+ * Returns an infinite sequential unordered stream where each element is
+ * generated by the provided {@code IntSupplier}. This is suitable for
+ * generating constant streams, streams of random elements, etc.
*
* @param s the {@code IntSupplier} for generated elements
- * @return a new sequential {@code IntStream}
+ * @return a new infinite sequential unordered {@code IntStream}
*/
public static IntStream generate(IntSupplier s) {
Objects.requireNonNull(s);
@@ -871,11 +828,16 @@
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
- * second stream. The resulting stream is ordered if both
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * @implNote
+ * Use caution when constructing streams from repeated concatenation.
+ * Accessing an element of a deeply concatenated stream can result in deep
+ * call chains, or even {@code StackOverflowException}.
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
diff --git a/src/share/classes/java/util/stream/LongStream.java b/src/share/classes/java/util/stream/LongStream.java
index 0b8fb15..d9fe6b3 100644
--- a/src/share/classes/java/util/stream/LongStream.java
+++ b/src/share/classes/java/util/stream/LongStream.java
@@ -51,9 +51,13 @@
import java.util.function.Supplier;
/**
- * A sequence of elements supporting sequential and parallel aggregate
- * operations. The following example illustrates an aggregate operation using
- * {@link Stream} and {@link LongStream}:
+ * A sequence of primitive long-valued elements supporting sequential and parallel
+ * aggregate operations. This is the {@code long} primitive specialization of
+ * {@link Stream}.
+ *
+ * <p>The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link LongStream}, computing the sum of the weights of the
+ * red widgets:
*
* <pre>{@code
* long sum = widgets.stream()
@@ -62,78 +66,13 @@
* .sum();
* }</pre>
*
- * In this example, {@code widgets} is a {@code Collection<Widget>}. We create
- * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
- * filter it to produce a stream containing only the red widgets, and then
- * transform it into a stream of {@code long} values representing the weight of
- * each red widget. Then this stream is summed to produce a total weight.
- *
- * <p>To perform a computation, stream
- * <a href="package-summary.html#StreamOps">operations</a> are composed into a
- * <em>stream pipeline</em>. A stream pipeline consists of a source (which
- * might be an array, a collection, a generator function, an IO channel,
- * etc), zero or more <em>intermediate operations</em> (which transform a
- * stream into another stream, such as {@link LongStream#filter(LongPredicate)}), and a
- * <em>terminal operation</em> (which produces a result or side-effect, such
- * as {@link LongStream#sum()} or {@link LongStream#forEach(LongConsumer)}).
- * Streams are lazy; computation on the source data is only performed when the
- * terminal operation is initiated, and source elements are consumed only
- * as needed.
- *
- * <p>Collections and streams, while bearing some superficial similarities,
- * have different goals. Collections are primarily concerned with the efficient
- * management of, and access to, their elements. By contrast, streams do not
- * provide a means to directly access or manipulate their elements, and are
- * instead concerned with declaratively describing their source and the
- * computational operations which will be performed in aggregate on that source.
- * However, if the provided stream operations do not offer the desired
- * functionality, the {@link #iterator()} and {@link #spliterator()} operations
- * can be used to perform a controlled traversal.
- *
- * <p>A stream pipeline, like the "widgets" example above, can be viewed as
- * a <em>query</em> on the stream source. Unless the source was explicitly
- * designed for concurrent modification (such as a {@link ConcurrentHashMap}),
- * unpredictable or erroneous behavior may result from modifying the stream
- * source while it is being queried.
- *
- * <p>Most stream operations accept parameters that describe user-specified
- * behavior, such as the lambda expression {@code w -> w.getWeight()} passed to
- * {@code mapToLong} in the example above. Such parameters are always instances
- * of a <a href="../function/package-summary.html">functional interface</a> such
- * as {@link java.util.function.Function}, and are often lambda expressions or
- * method references. These parameters can never be null, should not modify the
- * stream source, and should be
- * <a href="package-summary.html#NonInterference">effectively stateless</a>
- * (their result should not depend on any state that might change during
- * execution of the stream pipeline.)
- *
- * <p>A stream should be operated on (invoking an intermediate or terminal stream
- * operation) only once. This rules out, for example, "forked" streams, where
- * the same source feeds two or more pipelines, or multiple traversals of the
- * same stream. A stream implementation may throw {@link IllegalStateException}
- * if it detects that the stream is being reused. However, since some stream
- * operations may return their receiver rather than a new stream object, it may
- * not be possible to detect reuse in all cases.
- *
- * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
- * but nearly all stream instances do not actually need to be closed after use.
- * Generally, only streams whose source is an IO channel (such as those returned
- * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
- * are backed by collections, arrays, or generating functions, which require no
- * special resource management. (If a stream does require closing, it can be
- * declared as a resource in a {@code try}-with-resources statement.)
- *
- * <p>Stream pipelines may execute either sequentially or in
- * <a href="package-summary.html#Parallelism">parallel</a>. This
- * execution mode is a property of the stream. Streams are created
- * with an initial choice of sequential or parallel execution. (For example,
- * {@link Collection#stream() Collection.stream()} creates a sequential stream,
- * and {@link Collection#parallelStream() Collection.parallelStream()} creates
- * a parallel one.) This choice of execution mode may be modified by the
- * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
- * the {@link #isParallel()} method.
+ * See the class documentation for {@link Stream} and the package documentation
+ * for <a href="package-summary.html">java.util.stream</a> for additional
+ * specification of streams, stream operations, stream pipelines, and
+ * parallelism.
*
* @since 1.8
+ * @see Stream
* @see <a href="package-summary.html">java.util.stream</a>
*/
public interface LongStream extends BaseStream<Long, LongStream> {
@@ -145,9 +84,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> predicate to apply to
- * each element to determine if it should be included
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to each element to determine if it
+ * should be included
* @return the new stream
*/
LongStream filter(LongPredicate predicate);
@@ -159,9 +99,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
LongStream map(LongUnaryOperator mapper);
@@ -174,9 +114,9 @@
* intermediate operation</a>.
*
* @param <U> the element type of the new stream
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
<U> Stream<U> mapToObj(LongFunction<? extends U> mapper);
@@ -188,9 +128,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
IntStream mapToInt(LongToIntFunction mapper);
@@ -202,9 +142,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
DoubleStream mapToDouble(LongToDoubleFunction mapper);
@@ -219,10 +159,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to
- * each element which produces an {@code LongStream} of new
- * values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a
+ * {@code LongStream} of new values
* @return the new stream
* @see Stream#flatMap(Function)
*/
@@ -421,9 +361,10 @@
* synchronization and with greatly reduced risk of data races.
*
* @param identity the identity value for the accumulating function
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #sum()
* @see #min()
@@ -460,9 +401,10 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @param op an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param op an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
* @see #reduce(long, LongBinaryOperator)
*/
@@ -492,14 +434,15 @@
* @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called
* multiple times and must return a fresh value each time.
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for incorporating an additional
- * element into a result
- * @param combiner an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values, which
- * must be compatible with the accumulator function
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for incorporating an additional element into a result
+ * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values, which must be
+ * compatible with the accumulator function
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@@ -599,48 +542,67 @@
/**
* Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not
- * necessary for determining the result.
+ * necessary for determining the result. If the stream is empty then
+ * {@code false} is returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
+ * @apiNote
+ * This method evaluates the <em>existential quantification</em> of the
+ * predicate over the elements of the stream (for some x P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided
- * predicate otherwise {@code false}
+ * predicate, otherwise {@code false}
*/
boolean anyMatch(LongPredicate predicate);
/**
* Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if all elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * predicate over the elements of the stream (for all x P(x)). If the
+ * stream is empty, the quantification is said to be <em>vacuously
+ * satisfied</em> and is always {@code true} (regardless of P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either all elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean allMatch(LongPredicate predicate);
/**
- * Returns whether no elements of this stream match the provided predicate.
+ * Returns whether no elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if no elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * negated predicate over the elements of the stream (for all x ~P(x)). If
+ * the stream is empty, the quantification is said to be vacuously satisfied
+ * and is always {@code true}, regardless of P(x).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either no elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean noneMatch(LongPredicate predicate);
@@ -791,12 +753,12 @@
}
/**
- * Returns a sequential stream where each element is generated by
- * the provided {@code LongSupplier}. This is suitable for generating
- * constant streams, streams of random elements, etc.
+ * Returns an infinite sequential unordered stream where each element is
+ * generated by the provided {@code LongSupplier}. This is suitable for
+ * generating constant streams, streams of random elements, etc.
*
* @param s the {@code LongSupplier} for generated elements
- * @return a new sequential {@code LongStream}
+ * @return a new infinite sequential unordered {@code LongStream}
*/
public static LongStream generate(LongSupplier s) {
Objects.requireNonNull(s);
@@ -874,11 +836,16 @@
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
- * second stream. The resulting stream is ordered if both
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * @implNote
+ * Use caution when constructing streams from repeated concatenation.
+ * Accessing an element of a deeply concatenated stream can result in deep
+ * call chains, or even {@code StackOverflowException}.
+ *
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
diff --git a/src/share/classes/java/util/stream/Node.java b/src/share/classes/java/util/stream/Node.java
index 381d06d..2b4360b 100644
--- a/src/share/classes/java/util/stream/Node.java
+++ b/src/share/classes/java/util/stream/Node.java
@@ -241,6 +241,7 @@
* @param action a consumer that is to be invoked with each
* element in this {@code Node.OfPrimitive}
*/
+ @SuppressWarnings("overloads")
void forEach(T_CONS action);
@Override
diff --git a/src/share/classes/java/util/stream/SpinedBuffer.java b/src/share/classes/java/util/stream/SpinedBuffer.java
index e7fac67..878b2c2 100644
--- a/src/share/classes/java/util/stream/SpinedBuffer.java
+++ b/src/share/classes/java/util/stream/SpinedBuffer.java
@@ -579,6 +579,7 @@
spineIndex = 0;
}
+ @SuppressWarnings("overloads")
public void forEach(T_CONS consumer) {
// completed chunks, if any
for (int j = 0; j < spineIndex; j++)
diff --git a/src/share/classes/java/util/stream/Stream.java b/src/share/classes/java/util/stream/Stream.java
index 1961359..9c88e68 100644
--- a/src/share/classes/java/util/stream/Stream.java
+++ b/src/share/classes/java/util/stream/Stream.java
@@ -67,6 +67,11 @@
* transform it into a stream of {@code int} values representing the weight of
* each red widget. Then this stream is summed to produce a total weight.
*
+ * <p>In addition to {@code Stream}, which is a stream of object references,
+ * there are primitive specializations for {@link IntStream}, {@link LongStream},
+ * and {@link DoubleStream}, all of which are referred to as "streams" and
+ * conform to the characteristics and restrictions described here.
+ *
* <p>To perform a computation, stream
* <a href="package-summary.html#StreamOps">operations</a> are composed into a
* <em>stream pipeline</em>. A stream pipeline consists of a source (which
@@ -97,14 +102,21 @@
*
* <p>Most stream operations accept parameters that describe user-specified
* behavior, such as the lambda expression {@code w -> w.getWeight()} passed to
- * {@code mapToInt} in the example above. Such parameters are always instances
- * of a <a href="../function/package-summary.html">functional interface</a> such
+ * {@code mapToInt} in the example above. To preserve correct behavior,
+ * these <em>behavioral parameters</em>:
+ * <ul>
+ * <li>must be <a href="package-summary.html#NonInterference">non-interfering</a>
+ * (they do not modify the stream source); and</li>
+ * <li>in most cases must be <a href="package-summary.html#Statelessness">stateless</a>
+ * (their result should not depend on any state that might change during execution
+ * of the stream pipeline).</li>
+ * </ul>
+ *
+ * <p>Such parameters are always instances of a
+ * <a href="../function/package-summary.html">functional interface</a> such
* as {@link java.util.function.Function}, and are often lambda expressions or
- * method references. These parameters can never be null, should not modify the
- * stream source, and should be
- * <a href="package-summary.html#NonInterference">effectively stateless</a>
- * (their result should not depend on any state that might change during
- * execution of the stream pipeline.)
+ * method references. Unless otherwise specified these parameters must be
+ * <em>non-null</em>.
*
* <p>A stream should be operated on (invoking an intermediate or terminal stream
* operation) only once. This rules out, for example, "forked" streams, where
@@ -134,6 +146,9 @@
*
* @param <T> the type of the stream elements
* @since 1.8
+ * @see IntStream
+ * @see LongStream
+ * @see DoubleStream
* @see <a href="package-summary.html">java.util.stream</a>
*/
public interface Stream<T> extends BaseStream<T, Stream<T>> {
@@ -145,9 +160,10 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> predicate to apply to
- * each element to determine if it should be included
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to each element to determine if it
+ * should be included
* @return the new stream
*/
Stream<T> filter(Predicate<? super T> predicate);
@@ -160,9 +176,9 @@
* operation</a>.
*
* @param <R> The element type of the new stream
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
@@ -174,9 +190,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">
* intermediate operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
IntStream mapToInt(ToIntFunction<? super T> mapper);
@@ -188,9 +204,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
LongStream mapToLong(ToLongFunction<? super T> mapper);
@@ -202,9 +218,9 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element
* @return the new stream
*/
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
@@ -221,19 +237,33 @@
*
* @apiNote
* The {@code flatMap()} operation has the effect of applying a one-to-many
- * tranformation to the elements of the stream, and then flattening the
- * resulting elements into a new stream. For example, if {@code orders}
- * is a stream of purchase orders, and each purchase order contains a
- * collection of line items, then the following produces a stream of line
- * items:
+ * transformation to the elements of the stream, and then flattening the
+ * resulting elements into a new stream.
+ *
+ * <p><b>Examples.</b>
+ *
+ * <p>If {@code orders} is a stream of purchase orders, and each purchase
+ * order contains a collection of line items, then the following produces a
+ * stream containing all the line items in all the orders:
* <pre>{@code
- * orderStream.flatMap(order -> order.getLineItems().stream())...
+ * orders.flatMap(order -> order.getLineItems().stream())...
* }</pre>
*
+ * <p>If {@code path} is the path to a file, then the following produces a
+ * stream of the {@code words} contained in that file:
+ * <pre>{@code
+ * Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);
+ * Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
+ * }</pre>
+ * The {@code mapper} function passed to {@code flatMap} splits a line,
+ * using a simple regular expression, into an array of words, and then
+ * creates a stream of words from that array.
+ *
* @param <R> The element type of the new stream
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element which produces a stream of new values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a stream
+ * of new values
* @return the new stream
*/
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
@@ -248,10 +278,12 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element which produces a stream of new values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a stream
+ * of new values
* @return the new stream
+ * @see #flatMap(Function)
*/
IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
@@ -265,10 +297,12 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to
- * each element which produces a stream of new values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a stream
+ * of new values
* @return the new stream
+ * @see #flatMap(Function)
*/
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
@@ -282,10 +316,12 @@
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @param mapper a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> function to apply to each
- * element which produces a stream of new values
+ * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function to apply to each element which produces a stream
+ * of new values
* @return the new stream
+ * @see #flatMap(Function)
*/
DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
@@ -293,9 +329,27 @@
* Returns a stream consisting of the distinct elements (according to
* {@link Object#equals(Object)}) of this stream.
*
+ * <p>For ordered streams, the selection of distinct elements is stable
+ * (for duplicated elements, the element appearing first in the encounter
+ * order is preserved.) For unordered streams, no stability guarantees
+ * are made.
+ *
* <p>This is a <a href="package-summary.html#StreamOps">stateful
* intermediate operation</a>.
*
+ * @apiNote
+ * Preserving stability for {@code distinct()} in parallel pipelines is
+ * relatively expensive (requires that the operation act as a full barrier,
+ * with substantial buffering overhead), and stability is often not needed.
+ * Using an unordered stream source (such as {@link #generate(Supplier)})
+ * or removing the ordering constraint with {@link #unordered()} may result
+ * in significantly more efficient execution for {@code distinct()} in parallel
+ * pipelines, if the semantics of your situation permit. If consistency
+ * with encounter order is required, and you are experiencing poor performance
+ * or memory utilization with {@code distinct()} in parallel pipelines,
+ * switching to sequential execution with {@link #sequential()} may improve
+ * performance.
+ *
* @return the new stream
*/
Stream<T> distinct();
@@ -306,6 +360,9 @@
* {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown
* when the terminal operation is executed.
*
+ * <p>For ordered streams, the sort is stable. For unordered streams, no
+ * stability guarantees are made.
+ *
* <p>This is a <a href="package-summary.html#StreamOps">stateful
* intermediate operation</a>.
*
@@ -317,12 +374,15 @@
* Returns a stream consisting of the elements of this stream, sorted
* according to the provided {@code Comparator}.
*
+ * <p>For ordered streams, the sort is stable. For unordered streams, no
+ * stability guarantees are made.
+ *
* <p>This is a <a href="package-summary.html#StreamOps">stateful
* intermediate operation</a>.
*
- * @param comparator a <a href="package-summary.html#NonInterference">
- * non-interfering, stateless</a> {@code Comparator} to
- * be used to compare stream elements
+ * @param comparator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * {@code Comparator} to be used to compare stream elements
* @return the new stream
*/
Stream<T> sorted(Comparator<? super T> comparator);
@@ -420,7 +480,8 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * <p>For parallel stream pipelines, this operation does <em>not</em>
+ * <p>The behavior of this operation is explicitly nondeterministic.
+ * For parallel stream pipelines, this operation does <em>not</em>
* guarantee to respect the encounter order of the stream, as doing so
* would sacrifice the benefit of parallelism. For any given element, the
* action may be performed at whatever time and in whatever thread the
@@ -433,13 +494,18 @@
void forEach(Consumer<? super T> action);
/**
- * Performs an action for each element of this stream, guaranteeing that
- * each element is processed in encounter order for streams that have a
- * defined encounter order.
+ * Performs an action for each element of this stream, in the encounter
+ * order of the stream if the stream has a defined encounter order.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
+ * <p>This operation processes the elements one at a time, in encounter
+ * order if one exists. Performing the action for one element
+ * <a href="../concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
+ * performing the action for subsequent elements, but for any given element,
+ * the action may be performed in whatever thread the library chooses.
+ *
* @param action a <a href="package-summary.html#NonInterference">
* non-interfering</a> action to perform on the elements
* @see #forEach(Consumer)
@@ -528,9 +594,10 @@
* synchronization and with greatly reduced risk of data races.
*
* @param identity the identity value for the accumulating function
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return the result of the reduction
*/
T reduce(T identity, BinaryOperator<T> accumulator);
@@ -563,14 +630,15 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values
* @return an {@link Optional} describing the result of the reduction
* @throws NullPointerException if the result of the reduction is null
* @see #reduce(Object, BinaryOperator)
- * @see #min(java.util.Comparator)
- * @see #max(java.util.Comparator)
+ * @see #min(Comparator)
+ * @see #max(Comparator)
*/
Optional<T> reduce(BinaryOperator<T> accumulator);
@@ -608,14 +676,15 @@
*
* @param <U> The type of the result
* @param identity the identity value for the combiner function
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for incorporating an additional
- * element into a result
- * @param combiner an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values, which
- * must be compatible with the accumulator function
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for incorporating an additional element into a result
+ * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values, which must be
+ * compatible with the accumulator function
* @return the result of the reduction
* @see #reduce(BinaryOperator)
* @see #reduce(Object, BinaryOperator)
@@ -664,14 +733,15 @@
* @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called
* multiple times and must return a fresh value each time.
- * @param accumulator an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for incorporating an additional
- * element into a result
- * @param combiner an <a href="package-summary.html#Associativity">associative</a>
- * <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> function for combining two values, which
- * must be compatible with the accumulator function
+ * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for incorporating an additional element into a result
+ * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
+ * <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * function for combining two values, which must be
+ * compatible with the accumulator function
* @return the result of the reduction
*/
<R> R collect(Supplier<R> supplier,
@@ -687,6 +757,13 @@
* collection strategies and composition of collect operations such as
* multiple-level grouping or partitioning.
*
+ * <p>If the stream is parallel, and the {@code Collector}
+ * is {@link Collector.Characteristics#CONCURRENT concurrent}, and
+ * either the stream is unordered or the collector is
+ * {@link Collector.Characteristics#UNORDERED unordered},
+ * then a concurrent reduction will be performed (see {@link Collector} for
+ * details on concurrent reduction.)
+ *
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
@@ -732,9 +809,9 @@
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
*
- * @param comparator a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> {@code Comparator} to use to compare
- * elements of this stream
+ * @param comparator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * {@code Comparator} to compare elements of this stream
* @return an {@code Optional} describing the minimum element of this stream,
* or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the minimum element is null
@@ -749,9 +826,9 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
- * @param comparator a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> {@code Comparator} to use to compare
- * elements of this stream
+ * @param comparator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * {@code Comparator} to compare elements of this stream
* @return an {@code Optional} describing the maximum element of this stream,
* or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the maximum element is null
@@ -775,48 +852,67 @@
/**
* Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not
- * necessary for determining the result.
+ * necessary for determining the result. If the stream is empty then
+ * {@code false} is returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
+ * @apiNote
+ * This method evaluates the <em>existential quantification</em> of the
+ * predicate over the elements of the stream (for some x P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided
- * predicate otherwise {@code false}
+ * predicate, otherwise {@code false}
*/
boolean anyMatch(Predicate<? super T> predicate);
/**
* Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if all elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * predicate over the elements of the stream (for all x P(x)). If the
+ * stream is empty, the quantification is said to be <em>vacuously
+ * satisfied</em> and is always {@code true} (regardless of P(x)).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either all elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean allMatch(Predicate<? super T> predicate);
/**
* Returns whether no elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
- * determining the result.
+ * determining the result. If the stream is empty then {@code true} is
+ * returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
- * @param predicate a <a href="package-summary.html#NonInterference">non-interfering,
- * stateless</a> predicate to apply to elements of this
- * stream
- * @return {@code true} if no elements of the stream match the provided
- * predicate otherwise {@code false}
+ * @apiNote
+ * This method evaluates the <em>universal quantification</em> of the
+ * negated predicate over the elements of the stream (for all x ~P(x)). If
+ * the stream is empty, the quantification is said to be vacuously satisfied
+ * and is always {@code true}, regardless of P(x).
+ *
+ * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
+ * <a href="package-summary.html#Statelessness">stateless</a>
+ * predicate to apply to elements of this stream
+ * @return {@code true} if either no elements of the stream match the
+ * provided predicate or the stream is empty, otherwise {@code false}
*/
boolean noneMatch(Predicate<? super T> predicate);
@@ -939,13 +1035,13 @@
}
/**
- * Returns a sequential stream where each element is generated by
- * the provided {@code Supplier}. This is suitable for generating
- * constant streams, streams of random elements, etc.
+ * Returns an infinite sequential unordered stream where each element is
+ * generated by the provided {@code Supplier}. This is suitable for
+ * generating constant streams, streams of random elements, etc.
*
* @param <T> the type of stream elements
* @param s the {@code Supplier} of generated elements
- * @return a new sequential {@code Stream}
+ * @return a new infinite sequential unordered {@code Stream}
*/
public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
@@ -956,11 +1052,16 @@
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
- * second stream. The resulting stream is ordered if both
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
+ * @implNote
+ * Use caution when constructing streams from repeated concatenation.
+ * Accessing an element of a deeply concatenated stream can result in deep
+ * call chains, or even {@code StackOverflowException}.
+ *
* @param <T> The type of stream elements
* @param a the first stream
* @param b the second stream
diff --git a/src/share/classes/java/util/stream/StreamSpliterators.java b/src/share/classes/java/util/stream/StreamSpliterators.java
index f7b7842..7322773 100644
--- a/src/share/classes/java/util/stream/StreamSpliterators.java
+++ b/src/share/classes/java/util/stream/StreamSpliterators.java
@@ -27,6 +27,7 @@
import java.util.Comparator;
import java.util.Objects;
import java.util.Spliterator;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
@@ -1227,6 +1228,88 @@
}
/**
+ * A wrapping spliterator that only reports distinct elements of the
+ * underlying spliterator. Does not preserve size and encounter order.
+ */
+ static final class DistinctSpliterator<T> implements Spliterator<T>, Consumer<T> {
+
+ // The value to represent null in the ConcurrentHashMap
+ private static final Object NULL_VALUE = new Object();
+
+ // The underlying spliterator
+ private final Spliterator<T> s;
+
+ // ConcurrentHashMap holding distinct elements as keys
+ private final ConcurrentHashMap<T, Boolean> seen;
+
+ // Temporary element, only used with tryAdvance
+ private T tmpSlot;
+
+ DistinctSpliterator(Spliterator<T> s) {
+ this(s, new ConcurrentHashMap<>());
+ }
+
+ private DistinctSpliterator(Spliterator<T> s, ConcurrentHashMap<T, Boolean> seen) {
+ this.s = s;
+ this.seen = seen;
+ }
+
+ @Override
+ public void accept(T t) {
+ this.tmpSlot = t;
+ }
+
+ @SuppressWarnings("unchecked")
+ private T mapNull(T t) {
+ return t != null ? t : (T) NULL_VALUE;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer<? super T> action) {
+ while (s.tryAdvance(this)) {
+ if (seen.putIfAbsent(mapNull(tmpSlot), Boolean.TRUE) == null) {
+ action.accept(tmpSlot);
+ tmpSlot = null;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super T> action) {
+ s.forEachRemaining(t -> {
+ if (seen.putIfAbsent(mapNull(t), Boolean.TRUE) == null) {
+ action.accept(t);
+ }
+ });
+ }
+
+ @Override
+ public Spliterator<T> trySplit() {
+ Spliterator<T> split = s.trySplit();
+ return (split != null) ? new DistinctSpliterator<>(split, seen) : null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return s.estimateSize();
+ }
+
+ @Override
+ public int characteristics() {
+ return (s.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.SORTED | Spliterator.ORDERED))
+ | Spliterator.DISTINCT;
+ }
+
+ @Override
+ public Comparator<? super T> getComparator() {
+ return s.getComparator();
+ }
+ }
+
+ /**
* A Spliterator that infinitely supplies elements in no particular order.
*
* <p>Splitting divides the estimated size in two and stops when the
diff --git a/src/share/classes/java/util/stream/StreamSupport.java b/src/share/classes/java/util/stream/StreamSupport.java
index 6feadd1..70af2da 100644
--- a/src/share/classes/java/util/stream/StreamSupport.java
+++ b/src/share/classes/java/util/stream/StreamSupport.java
@@ -96,7 +96,8 @@
* @param supplier a {@code Supplier} of a {@code Spliterator}
* @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator}. The characteristics must be equal to
- * {@code supplier.get().characteristics()}.
+ * {@code supplier.get().characteristics()}, otherwise undefined
+ * behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
@@ -163,7 +164,8 @@
* @param supplier a {@code Supplier} of a {@code Spliterator.OfInt}
* @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfInt}. The characteristics must be equal to
- * {@code supplier.get().characteristics()}
+ * {@code supplier.get().characteristics()}, otherwise undefined
+ * behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
@@ -230,7 +232,8 @@
* @param supplier a {@code Supplier} of a {@code Spliterator.OfLong}
* @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfLong}. The characteristics must be equal to
- * {@code supplier.get().characteristics()}
+ * {@code supplier.get().characteristics()}, otherwise undefined
+ * behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
@@ -297,7 +300,8 @@
* @param supplier A {@code Supplier} of a {@code Spliterator.OfDouble}
* @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfDouble}. The characteristics must be equal to
- * {@code supplier.get().characteristics()}
+ * {@code supplier.get().characteristics()}, otherwise undefined
+ * behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
diff --git a/src/share/classes/java/util/stream/package-info.java b/src/share/classes/java/util/stream/package-info.java
index 440054e..810e2fc 100644
--- a/src/share/classes/java/util/stream/package-info.java
+++ b/src/share/classes/java/util/stream/package-info.java
@@ -219,31 +219,18 @@
* <em>not modified at all</em> during the execution of the stream pipeline.
* The notable exception to this are streams whose sources are concurrent
* collections, which are specifically designed to handle concurrent modification.
+ * Concurrent stream sources are those whose {@code Spliterator} reports the
+ * {@code CONCURRENT} characteristic.
*
- * <p>Accordingly, behavioral parameters passed to stream methods should never
- * modify the stream's data source. An implementation is said to
- * <em>interfere</em> with the data source if it modifies, or causes to be
+ * <p>Accordingly, behavioral parameters in stream pipelines whose source might
+ * not be concurrent should never modify the stream's data source.
+ * A behavioral parameter is said to <em>interfere</em> with a non-concurrent
+ * data source if it modifies, or causes to be
* modified, the stream's data source. The need for non-interference applies
* to all pipelines, not just parallel ones. Unless the stream source is
* concurrent, modifying a stream's data source during execution of a stream
* pipeline can cause exceptions, incorrect answers, or nonconformant behavior.
*
- * <p>Results may be nondeterministic or incorrect if the behavioral
- * parameters of stream operations are <em>stateful</em>. A stateful lambda
- * (or other object implementing the appropriate functional interface) is one
- * whose result depends on any state which might change during the execution
- * of the stream pipeline. An example of a stateful lambda is:
- *
- * <pre>{@code
- * Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
- * stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
- * }</pre>
- *
- * Here, if the mapping operation is performed in parallel, the results for the
- * same input could vary from run to run, due to thread scheduling differences,
- * whereas, with a stateless lambda expression the results would always be the
- * same.
- *
* For well-behaved stream sources, the source can be modified before the
* terminal operation commences and those modifications will be reflected in
* the covered elements. For example, consider the following code:
@@ -265,26 +252,54 @@
* <a href="package-summary.html#StreamSources">Low-level stream
* construction</a> for requirements for building well-behaved streams.
*
- * <p>Some streams, particularly those whose stream sources are concurrent, can
- * tolerate concurrent modification during execution of a stream pipeline.
- * However, in no case -- even if the stream source is concurrent -- should
- * behavioral parameters to stream operations modify the stream source. Modifying
- * the stream source from within the stream source may cause pipeline execution
- * to fail to terminate, produce inaccurate results, or throw exceptions.
- * The following example shows inappropriate interference with the source:
+ * <h3><a name="Statelessness">Stateless behaviors</a></h3>
+ *
+ * Stream pipeline results may be nondeterministic or incorrect if the behavioral
+ * parameters to the stream operations are <em>stateful</em>. A stateful lambda
+ * (or other object implementing the appropriate functional interface) is one
+ * whose result depends on any state which might change during the execution
+ * of the stream pipeline. An example of a stateful lambda is the parameter
+ * to {@code map()} in:
+ *
* <pre>{@code
- * // Don't do this!
- * List<String> l = new ArrayList(Arrays.asList("one", "two"));
- * Stream<String> sl = l.stream();
- * String s = sl.peek(s -> l.add("BAD LAMBDA")).collect(joining(" "));
+ * Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
+ * stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
* }</pre>
*
+ * Here, if the mapping operation is performed in parallel, the results for the
+ * same input could vary from run to run, due to thread scheduling differences,
+ * whereas, with a stateless lambda expression the results would always be the
+ * same.
+ *
+ * <p>Note also that attempting to access mutable state from behavioral parameters
+ * presents you with a bad choice with respect to safety and performance; if
+ * you do not synchronize access to that state, you have a data race and
+ * therefore your code is broken, but if you do synchronize access to that
+ * state, you risk having contention undermine the parallelism you are seeking
+ * to benefit from. The best approach is to avoid stateful behavioral
+ * parameters to stream operations entirely; there is usually a way to
+ * restructure the stream pipeline to avoid statefulness.
+ *
* <h3>Side-effects</h3>
*
* Side-effects in behavioral parameters to stream operations are, in general,
* discouraged, as they can often lead to unwitting violations of the
- * statelessness requirement, as well as other thread-safety hazards. Many
- * computations where one might be tempted to use side effects can be more
+ * statelessness requirement, as well as other thread-safety hazards.
+ *
+ * <p>If the behavioral parameters do have side-effects, unless explicitly
+ * stated, there are no guarantees as to the
+ * <a href="../concurrent/package-summary.html#MemoryVisibility"><i>visibility</i></a>
+ * of those side-effects to other threads, nor are there any guarantees that
+ * different operations on the "same" element within the same stream pipeline
+ * are executed in the same thread. Further, the ordering of those effects
+ * may be surprising. Even when a pipeline is constrained to produce a
+ * <em>result</em> that is consistent with the encounter order of the stream
+ * source (for example, {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
+ * must produce {@code [0, 2, 4, 6, 8]}), no guarantees are made as to the order
+ * in which the mapper function is applied to individual elements, or in what
+ * thread any behavioral parameter is executed for a given element.
+ *
+ * <p>Many computations where one might be tempted to use side effects can be more
* safely and efficiently expressed without side-effects, such as using
* <a href="package-summary.html#Reduction">reduction</a> instead of mutable
* accumulators. However, side-effects such as using {@code println()} for debugging
diff --git a/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java b/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java
index 65c81cc..cd8e3ac 100644
--- a/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java
+++ b/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java
@@ -120,6 +120,7 @@
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
+ // Note: classNames is guaranteed by the constructor to be non-null.
for (int i = 0; i < classNames.length; i++) {
if (name.equals(classNames[i])) {
return defineClass(classNames[i], byteCodes[i], 0,
diff --git a/src/share/classes/javax/naming/CompositeName.java b/src/share/classes/javax/naming/CompositeName.java
index ffa837d..7c79d52 100644
--- a/src/share/classes/javax/naming/CompositeName.java
+++ b/src/share/classes/javax/naming/CompositeName.java
@@ -41,7 +41,7 @@
* This range may be written as [0,N).
* The most significant component is at index 0.
* An empty composite name has no components.
- *<p>
+ *
* <h1>JNDI Composite Name Syntax</h1>
* JNDI defines a standard string representation for composite names. This
* representation is the concatenation of the components of a composite name
@@ -72,12 +72,12 @@
* A trailing component separator (the composite name string ends with
* a separator) denotes a trailing empty component.
* Adjacent component separators denote an empty component.
- *<p>
+ *
*<h1>Composite Name Examples</h1>
*This table shows examples of some composite names. Each row shows
*the string form of a composite name and its corresponding structural form
*(<tt>CompositeName</tt>).
- *<p>
+ *
<table border="1" cellpadding=3 summary="examples showing string form of composite name and its corresponding structural form (CompositeName)">
<tr>
@@ -136,7 +136,7 @@
<td>{"x", "", "y"}</td>
</tr>
</table>
- * <p>
+ *
*<h1>Composition Examples</h1>
* Here are some composition examples. The right column shows composing
* string composite names while the left column shows composing the
@@ -144,7 +144,7 @@
* string forms of two composite names simply involves concatenating
* their string forms together.
-<p> <table border="1" cellpadding=3 summary="composition examples showing string names and composite names">
+<table border="1" cellpadding=3 summary="composition examples showing string names and composite names">
<tr>
<th>String Names</th>
@@ -188,7 +188,7 @@
</tr>
</table>
- *<p>
+ *
*<h1>Multithreaded Access</h1>
* A <tt>CompositeName</tt> instance is not synchronized against concurrent
* multithreaded access. Multiple threads trying to access and modify a
diff --git a/src/share/classes/javax/naming/CompoundName.java b/src/share/classes/javax/naming/CompoundName.java
index 49269e6..6d41cf8 100644
--- a/src/share/classes/javax/naming/CompoundName.java
+++ b/src/share/classes/javax/naming/CompoundName.java
@@ -38,7 +38,7 @@
* This range may be written as [0,N).
* The most significant component is at index 0.
* An empty compound name has no components.
- *<p>
+ *
* <h1>Compound Name Syntax</h1>
* The syntax of a compound name is specified using a set of properties:
*<dl>
@@ -135,7 +135,7 @@
* applied (e.g. embedded separators are escaped or quoted)
* so that when the same string is parsed, it will yield the same components
* of the original compound name.
- *<p>
+ *
*<h1>Multithreaded Access</h1>
* A <tt>CompoundName</tt> instance is not synchronized against concurrent
* multithreaded access. Multiple threads trying to access and modify a
diff --git a/src/share/classes/javax/naming/Context.java b/src/share/classes/javax/naming/Context.java
index 36040e7..db2acbd 100644
--- a/src/share/classes/javax/naming/Context.java
+++ b/src/share/classes/javax/naming/Context.java
@@ -31,7 +31,7 @@
* This interface represents a naming context, which
* consists of a set of name-to-object bindings.
* It contains methods for examining and updating these bindings.
- * <p>
+ *
* <h1>Names</h1>
* Each name passed as an argument to a <tt>Context</tt> method is relative
* to that context. The empty name is used to name the context itself.
@@ -68,12 +68,12 @@
* <tt>NamingEnumeration</tt> may be names in their own namespace rather than
* names in a composite namespace, at the discretion of the service
* provider.
- *<p>
+ *
*<h1>Exceptions</h1>
* All the methods in this interface can throw a <tt>NamingException</tt> or
* any of its subclasses. See <tt>NamingException</tt> and their subclasses
* for details on each exception.
- *<p>
+ *
*<h1>Concurrent Access</h1>
* A Context instance is not guaranteed to be synchronized against
* concurrent access by multiple threads. Threads that need to access
@@ -90,7 +90,7 @@
* use, or while any referrals generated by that operation are still
* being followed.
*
- *<p>
+ *
*<h1>Parameters</h1>
* A <tt>Name</tt> parameter passed to any method of the
* <tt>Context</tt> interface or one of its subinterfaces
@@ -102,7 +102,7 @@
* A <tt>Name</tt> returned by any such method is owned by the caller.
* The caller may subsequently modify it; the service provider may not.
*
- *<p>
+ *
*<h1>Environment Properties</h1>
*<p>
* JNDI applications need a way to communicate various preferences
diff --git a/src/share/classes/javax/naming/InitialContext.java b/src/share/classes/javax/naming/InitialContext.java
index 6a10cf6..7d5b6b4 100644
--- a/src/share/classes/javax/naming/InitialContext.java
+++ b/src/share/classes/javax/naming/InitialContext.java
@@ -361,7 +361,7 @@
* follows.
* Define a new method that uses this method to get an initial
* context of the desired subclass.
- * <p><blockquote><pre>
+ * <blockquote><pre>
* protected XXXContext getURLOrDefaultInitXXXCtx(Name name)
* throws NamingException {
* Context answer = getURLOrDefaultInitCtx(name);
@@ -377,7 +377,7 @@
* </pre></blockquote>
* When providing implementations for the new methods in the subclass,
* use this newly defined method to get the initial context.
- * <p><blockquote><pre>
+ * <blockquote><pre>
* public Object XXXMethod1(Name name, ...) {
* throws NamingException {
* return getURLOrDefaultInitXXXCtx(name).XXXMethod1(name, ...);
diff --git a/src/share/classes/javax/naming/ReferralException.java b/src/share/classes/javax/naming/ReferralException.java
index 23d77cf..7d3eaf3 100644
--- a/src/share/classes/javax/naming/ReferralException.java
+++ b/src/share/classes/javax/naming/ReferralException.java
@@ -156,7 +156,7 @@
* <code>getReferralContext</code> to allow the processing of
* other referrals to continue.
* The following code fragment shows a typical usage pattern.
- * <p><blockquote><pre>
+ * <blockquote><pre>
* } catch (ReferralException e) {
* if (!shallIFollow(e.getReferralInfo())) {
* if (!e.skipReferral()) {
@@ -177,7 +177,7 @@
* <code>getReferralContext</code> to allow the current
* referral to be retried.
* The following code fragment shows a typical usage pattern.
- * <p><blockquote><pre>
+ * <blockquote><pre>
* } catch (ReferralException e) {
* while (true) {
* try {
diff --git a/src/share/classes/javax/naming/directory/DirContext.java b/src/share/classes/javax/naming/directory/DirContext.java
index e372879..903ccbe 100644
--- a/src/share/classes/javax/naming/directory/DirContext.java
+++ b/src/share/classes/javax/naming/directory/DirContext.java
@@ -31,7 +31,7 @@
* The directory service interface, containing
* methods for examining and updating attributes
* associated with objects, and for searching the directory.
- * <p>
+ *
* <h1>Names</h1>
* Each name passed as an argument to a <tt>DirContext</tt> method is relative
* to that context. The empty name is used to name the context itself.
@@ -50,7 +50,7 @@
* See <tt>Context</tt> for a discussion on the interpretation of the
* name argument to the <tt>Context</tt> methods. These same rules
* apply to the name argument to the <tt>DirContext</tt> methods.
- * <p>
+ *
* <h1>Attribute Models</h1>
* There are two basic models of what attributes should be
* associated with. First, attributes may be directly associated with a
@@ -80,7 +80,7 @@
* JNDI clients are safest when they do not make assumptions about
* whether an object's attributes are stored as part of the object, or stored
* within the parent object and associated with the object's name.
- * <p>
+ *
* <h1>Attribute Type Names</h1>
* In the <tt>getAttributes()</tt> and <tt>search()</tt> methods,
* you can supply the attributes to return by supplying a list of
@@ -112,7 +112,7 @@
* <li>description;lang-fr
* </ul>
*
- * <p>
+ *
*<h1>Operational Attributes</h1>
*<p>
* Some directories have the notion of "operational attributes" which are
@@ -126,7 +126,7 @@
* The attributes returned do <em>not</em> include operational attributes.
* In order to retrieve operational attributes, you must name them explicitly.
*
- * <p>
+ *
* <h1>Named Context</h1>
* <p>
* There are certain methods in which the name must resolve to a context
@@ -137,7 +137,7 @@
* <code>NotContextException</code> is thrown.
* Aside from these methods, there is no requirement that the
* <em>named object</em> be a DirContext.
- *<p>
+ *
*<h1>Parameters</h1>
*<p>
* An <tt>Attributes</tt>, <tt>SearchControls</tt>, or array object
@@ -149,7 +149,7 @@
* An <tt>Attributes</tt> object returned by any method is owned by
* the caller. The caller may subsequently modify it; the service
* provider will not.
- *<p>
+ *
*<h1>Exceptions</h1>
*<p>
* All the methods in this interface can throw a NamingException or
diff --git a/src/share/classes/javax/naming/event/EventContext.java b/src/share/classes/javax/naming/event/EventContext.java
index fd44876..aacf161 100644
--- a/src/share/classes/javax/naming/event/EventContext.java
+++ b/src/share/classes/javax/naming/event/EventContext.java
@@ -33,7 +33,7 @@
/**
* Contains methods for registering/deregistering listeners to be notified of
* events fired when objects named in a context changes.
- *<p>
+ *
*<h1>Target</h1>
* The name parameter in the <tt>addNamingListener()</tt> methods is referred
* to as the <em>target</em>. The target, along with the scope, identify
@@ -58,7 +58,7 @@
* An application can use the method <tt>targetMustExist()</tt> to check
* whether a <tt>EventContext</tt> supports registration
* of nonexistent targets.
- *<p>
+ *
*<h1>Event Source</h1>
* The <tt>EventContext</tt> instance on which you invoke the
* registration methods is the <em>event source</em> of the events that are
diff --git a/src/share/classes/javax/naming/ldap/LdapContext.java b/src/share/classes/javax/naming/ldap/LdapContext.java
index 8cb5fb0..ef92b1c 100644
--- a/src/share/classes/javax/naming/ldap/LdapContext.java
+++ b/src/share/classes/javax/naming/ldap/LdapContext.java
@@ -338,7 +338,7 @@
* parameter, a system property, or one or more resource files.
*<p>
* The value of this constant is "java.naming.factory.control".
- *<p>
+ *
* @see ControlFactory
* @see javax.naming.Context#addToEnvironment
* @see javax.naming.Context#removeFromEnvironment
diff --git a/src/share/classes/javax/naming/ldap/Rdn.java b/src/share/classes/javax/naming/ldap/Rdn.java
index 943f230..a78fda3 100644
--- a/src/share/classes/javax/naming/ldap/Rdn.java
+++ b/src/share/classes/javax/naming/ldap/Rdn.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -315,7 +315,6 @@
* @return A negative integer, zero, or a positive integer as this Rdn
* is less than, equal to, or greater than the given Object.
* @exception ClassCastException if obj is null or not a Rdn.
- * <p>
*/
public int compareTo(Object obj) {
if (!(obj instanceof Rdn)) {
diff --git a/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java b/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java
index 188a1d7..0df0a99 100644
--- a/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java
+++ b/src/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java
@@ -27,6 +27,7 @@
import java.io.*;
import java.util.InvalidPropertiesFormatException;
+import java.util.Map.Entry;
import java.util.Properties;
import jdk.internal.org.xml.sax.Attributes;
import jdk.internal.org.xml.sax.InputSource;
@@ -107,12 +108,17 @@
writer.writeEndElement();
}
- for (String key : props.stringPropertyNames()) {
- String val = props.getProperty(key);
- writer.writeStartElement(ELEMENT_ENTRY);
- writer.writeAttribute(ATTR_KEY, key);
- writer.writeCharacters(val);
- writer.writeEndElement();
+ synchronized(props) {
+ for (Entry<Object, Object> e : props.entrySet()) {
+ final Object k = e.getKey();
+ final Object v = e.getValue();
+ if (k instanceof String && v instanceof String) {
+ writer.writeStartElement(ELEMENT_ENTRY);
+ writer.writeAttribute(ATTR_KEY, (String)k);
+ writer.writeCharacters((String)v);
+ writer.writeEndElement();
+ }
+ }
}
writer.writeEndElement();
diff --git a/src/share/classes/sun/applet/AppletClassLoader.java b/src/share/classes/sun/applet/AppletClassLoader.java
index fe8521e..a391197 100644
--- a/src/share/classes/sun/applet/AppletClassLoader.java
+++ b/src/share/classes/sun/applet/AppletClassLoader.java
@@ -239,6 +239,7 @@
* the "localhost".
*
* @param codesource the codesource
+ * @throws NullPointerException if {@code codesource} is {@code null}.
* @return the permissions granted to the codesource
*/
protected PermissionCollection getPermissions(CodeSource codesource)
diff --git a/src/share/classes/sun/launcher/resources/launcher_pt_BR.properties b/src/share/classes/sun/launcher/resources/launcher_pt_BR.properties
index 17d88fe..d2c68a0 100644
--- a/src/share/classes/sun/launcher/resources/launcher_pt_BR.properties
+++ b/src/share/classes/sun/launcher/resources/launcher_pt_BR.properties
@@ -34,7 +34,7 @@
java.launcher.ergo.message2 =\ porque a execu\u00E7\u00E3o est\u00E1 sendo feita em uma m\u00E1quina de classe de servidor.\n
# Translators please note do not translate the options themselves
-java.launcher.opt.footer =\ -cp <caminho de pesquisa da classe dos diret\u00F3rios e arquivos zip/jar>\n -classpath <caminho de pesquisa da classe dos diret\u00F3rios e arquivos zip/jar>\n Uma lista separada por {0} de diret\u00F3rios, archives JAR\n e archives ZIP nos quais ser\u00E3o procurados os arquivos de classe.\n -D<nome>=<valor>\n define uma propriedade do sistema\n -verbose:[classe|gc|jni]\n ativa a sa\u00EDda detalhada\n -version imprime a vers\u00E3o do produto e sai do programa\n -version:<valor>\n requer a execu\u00E7\u00E3o da vers\u00E3o especificada\n -showversion imprime a vers\u00E3o do produto e continua\n -jre-restrict-search | -no-jre-restrict-search\n inclui/exclui JREs privados do usu\u00E1rio na pesquisa de vers\u00E3o\n -? -help imprime esta mensagem de ajuda\n -X imprime a ajuda sobre op\u00E7\u00F5es n\u00E3o padronizadas\n -ea[:<nome do pacote>...|:<nome da classe>]\n -enableassertions[:<nome do pacote>...|:<nome da classe>]\n ativa asser\u00E7\u00F5es com granularidade especificada\n -da[:<nome do pacote>...|:<nome da classe>]\n -disableassertions[:<nome do pacote>...|:<nome da classe>]\n desativa asser\u00E7\u00F5es com granularidade especificada\n -esa | -enablesystemassertions\n ativa asser\u00E7\u00F5es do sistema\n -dsa | -disablesystemassertions\n desativa asser\u00E7\u00F5es do sistema\n -agentlib:<nome da biblioteca>[=<op\u00E7\u00F5es>]\n carrega a biblioteca de agentes nativa <nome da biblioteca>, por exemplo: -agentlib:hprof\n consulte tamb\u00E9m: -agentlib:jdwp=help e -agentlib:hprof=help\n -agentpath:<nome do caminho>[=<op\u00E7\u00F5es>]\n carrega a biblioteca de agentes nativa com base no nome do caminho completo\n -javaagent:<caminho do arquivo jar>[=<op\u00E7\u00F5es>]\n carrega o agente da linguagem de programa\u00E7\u00E3o Java; consulte java.lang.instrument\n -splash:<caminho da imagem>\n mostra a tela de abertura com a imagem especificada\nConsulte http://www.oracle.com/technetwork/java/javase/documentation/index.html para obter mais detalhes.
+java.launcher.opt.footer =\ -cp <caminho de pesquisa da classe dos diret\u00F3rios e arquivos zip/jar>\n -classpath <caminho de pesquisa da classe dos diret\u00F3rios e arquivos zip/jar>\n Uma lista separada por {0} de diret\u00F3rios, archives JAR\n e archives ZIP nos quais ser\u00E3o procurados os arquivos de classe.\n -D<nome>=<valor>\n define uma propriedade do sistema\n -verbose:[class|gc|jni]\n ativa a sa\u00EDda detalhada\n -version imprime a vers\u00E3o do produto e sai do programa\n -version:<valor>\n requer a execu\u00E7\u00E3o da vers\u00E3o especificada\n -showversion imprime a vers\u00E3o do produto e continua\n -jre-restrict-search | -no-jre-restrict-search\n inclui/exclui JREs privados do usu\u00E1rio na pesquisa de vers\u00E3o\n -? -help imprime esta mensagem de ajuda\n -X imprime a ajuda sobre op\u00E7\u00F5es n\u00E3o padronizadas\n -ea[:<nome do pacote>...|:<nome da classe>]\n -enableassertions[:<nome do pacote>...|:<nome da classe>]\n ativa asser\u00E7\u00F5es com granularidade especificada\n -da[:<nome do pacote>...|:<nome da classe>]\n -disableassertions[:<nome do pacote>...|:<nome da classe>]\n desativa asser\u00E7\u00F5es com granularidade especificada\n -esa | -enablesystemassertions\n ativa asser\u00E7\u00F5es do sistema\n -dsa | -disablesystemassertions\n desativa asser\u00E7\u00F5es do sistema\n -agentlib:<nome da biblioteca>[=<op\u00E7\u00F5es>]\n carrega a biblioteca de agentes nativa <nome da biblioteca>, por exemplo: -agentlib:hprof\n consulte tamb\u00E9m: -agentlib:jdwp=help e -agentlib:hprof=help\n -agentpath:<nome do caminho>[=<op\u00E7\u00F5es>]\n carrega a biblioteca de agentes nativa com base no nome do caminho completo\n -javaagent:<caminho do arquivo jar>[=<op\u00E7\u00F5es>]\n carrega o agente da linguagem de programa\u00E7\u00E3o Java; consulte java.lang.instrument\n -splash:<caminho da imagem>\n mostra a tela de abertura com a imagem especificada\nConsulte http://www.oracle.com/technetwork/java/javase/documentation/index.html para obter mais detalhes.
# Translators please note do not translate the options themselves
java.launcher.X.usage=\ -Xmixed execu\u00E7\u00E3o no modo misto (default)\n -Xint execu\u00E7\u00E3o somente no modo interpretado\n -Xbootclasspath:<diret\u00F3rios e arquivos zip/jar separados por {0}>\n define o caminho de pesquisa para classes e recursos de inicializa\u00E7\u00E3o\n -Xbootclasspath/a:<diret\u00F3rios e arquivos zip/jar separados por {0}>\n anexa no final do caminho da classe de inicializa\u00E7\u00E3o\n -Xbootclasspath/p:<diret\u00F3rios e arquivos zip/jar separados por {0}>\n anexa no in\u00EDcio do caminho da classe de inicializa\u00E7\u00E3o\n -Xdiag mostra mensagens de diagn\u00F3stico adicionais\n -Xnoclassgc desativa a coleta de lixo da classe\n -Xincgc ativa a coleta de lixo incremental\n -Xloggc:<arquivo> registra o status do GC status em um arquivo com marca\u00E7\u00F5es de data e hor\u00E1rio\n -Xbatch desativa a compila\u00E7\u00E3o em segundo plano\n -Xms<tamanho> define o tamanho inicial do heap Java\n -Xmx<tamanho> define o tamanho m\u00E1ximo do heap Java\n -Xss<tamanho> define o tamanho da pilha de threads java\n -Xprof produz dados de perfil da cpu\n -Xfuture ativa verifica\u00E7\u00F5es de n\u00EDvel m\u00E1ximo de exig\u00EAncia, prevendo o valor default futuro\n -Xrs reduz o uso de sinais do SO pelo(a) Java/VM (consulte a documenta\u00E7\u00E3o)\n -Xcheck:jni executa verifica\u00E7\u00F5es adicionais de fun\u00E7\u00F5es da JNI\n -Xshare:off n\u00E3o tenta usar dados da classe compartilhada\n -Xshare:auto se poss\u00EDvel, usa dados da classe compartilhada (default)\n -Xshare:on requer o uso de dados da classe compartilhada, caso contr\u00E1rio haver\u00E1 falha.\n -XshowSettings mostra todas as defini\u00E7\u00F5es e continua\n -XshowSettings:all\n mostra todas as defini\u00E7\u00F5es e continua\n -XshowSettings:vm mostra todas as defini\u00E7\u00F5es relacionadas \u00E0 vm e continua\n -XshowSettings:properties\n mostra todas as defini\u00E7\u00F5es da propriedade e continua\n -XshowSettings:locale\n mostra todas as defini\u00E7\u00F5es relativas \u00E0s configura\u00E7\u00F5es regionais e continua\n\nAs -X options n\u00E3o s\u00E3o padronizadas e est\u00E3o sujeitas a altera\u00E7\u00F5es sem aviso.\n
diff --git a/src/share/classes/sun/management/Agent.java b/src/share/classes/sun/management/Agent.java
index 238e9c1..171b5c9 100644
--- a/src/share/classes/sun/management/Agent.java
+++ b/src/share/classes/sun/management/Agent.java
@@ -323,7 +323,7 @@
: String.format(
"service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort);
- String instanceName = System.getProperty("com.sun.management.jdp.name");
+ String instanceName = props.getProperty("com.sun.management.jdp.name");
try{
JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
diff --git a/src/share/classes/sun/management/jdp/JdpController.java b/src/share/classes/sun/management/jdp/JdpController.java
index 3083c97..9b90b59 100644
--- a/src/share/classes/sun/management/jdp/JdpController.java
+++ b/src/share/classes/sun/management/jdp/JdpController.java
@@ -29,6 +29,12 @@
import java.net.UnknownHostException;
import java.util.UUID;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import sun.management.VMManagement;
+
/**
* JdpController is responsible to create and manage a broadcast loop
*
@@ -126,6 +132,25 @@
}
}
+ // Get the process id of the current running Java process
+ private static Integer getProcessId() {
+ try {
+ // Get the current process id using a reflection hack
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ Field jvm = runtime.getClass().getDeclaredField("jvm");
+ jvm.setAccessible(true);
+
+ VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+ Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+ pid_method.setAccessible(true);
+ Integer pid = (Integer) pid_method.invoke(mgmt);
+ return pid;
+ } catch(Exception ex) {
+ return null;
+ }
+ }
+
+
/**
* Starts discovery service
*
@@ -173,6 +198,20 @@
// it the key is skipped. PacketWriter is responsible to skip keys having null value.
packet.setInstanceName(instanceName);
+ // Set rmi server hostname if it explicitly specified by user with
+ // java.rmi.server.hostname
+ String rmiHostname = System.getProperty("java.rmi.server.hostname");
+ packet.setRmiHostname(rmiHostname);
+
+ // Set broadcast interval
+ packet.setBroadcastInterval(new Integer(pause).toString());
+
+ // Set process id
+ Integer pid = getProcessId();
+ if (pid != null) {
+ packet.setProcessId(pid.toString());
+ }
+
JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl);
// Stop discovery service if it's already running
diff --git a/src/share/classes/sun/management/jdp/JdpJmxPacket.java b/src/share/classes/sun/management/jdp/JdpJmxPacket.java
index 60aea2b..2ff2d18 100644
--- a/src/share/classes/sun/management/jdp/JdpJmxPacket.java
+++ b/src/share/classes/sun/management/jdp/JdpJmxPacket.java
@@ -64,11 +64,27 @@
* Name of Java instance
*/
public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME";
+ /**
+ * PID of java process, optional presented if it could be obtained
+ */
+ public final static String PROCESS_ID_KEY = "PROCESS_ID";
+ /**
+ * Hostname of rmi server, optional presented if user overrides rmi server
+ * hostname by java.rmi.server.hostname property
+ */
+ public final static String RMI_HOSTNAME_KEY = "RMI_HOSTNAME";
+ /**
+ * Configured broadcast interval, optional
+ */
+ public final static String BROADCAST_INTERVAL_KEY = "BROADCAST_INTERVAL";
private UUID id;
private String mainClass;
private String jmxServiceUrl;
private String instanceName;
+ private String processId;
+ private String rmiHostname;
+ private String broadcastInterval;
/**
* Create new instance from user provided data. Set mandatory fields
@@ -99,6 +115,9 @@
this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY);
this.mainClass = p.get(MAIN_CLASS_KEY);
this.instanceName = p.get(INSTANCE_NAME_KEY);
+ this.processId = p.get(PROCESS_ID_KEY);
+ this.rmiHostname = p.get(RMI_HOSTNAME_KEY);
+ this.broadcastInterval = p.get(BROADCAST_INTERVAL_KEY);
}
/**
@@ -150,6 +169,30 @@
return instanceName;
}
+ public String getProcessId() {
+ return processId;
+ }
+
+ public void setProcessId(String processId) {
+ this.processId = processId;
+ }
+
+ public String getRmiHostname() {
+ return rmiHostname;
+ }
+
+ public void setRmiHostname(String rmiHostname) {
+ this.rmiHostname = rmiHostname;
+ }
+
+ public String getBroadcastInterval() {
+ return broadcastInterval;
+ }
+
+ public void setBroadcastInterval(String broadcastInterval) {
+ this.broadcastInterval = broadcastInterval;
+ }
+
/**
*
* @return assembled packet ready to be sent across a Net
@@ -164,6 +207,10 @@
writer.addEntry(MAIN_CLASS_KEY, mainClass);
writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl);
writer.addEntry(INSTANCE_NAME_KEY, instanceName);
+ writer.addEntry(PROCESS_ID_KEY, processId);
+ writer.addEntry(RMI_HOSTNAME_KEY, rmiHostname);
+ writer.addEntry(BROADCAST_INTERVAL_KEY, broadcastInterval);
+
return writer.getPacketBytes();
}
diff --git a/src/share/classes/sun/misc/JavaLangAccess.java b/src/share/classes/sun/misc/JavaLangAccess.java
index fa844d4..7712647 100644
--- a/src/share/classes/sun/misc/JavaLangAccess.java
+++ b/src/share/classes/sun/misc/JavaLangAccess.java
@@ -28,6 +28,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.security.AccessControlContext;
+import java.util.Map;
import sun.reflect.ConstantPool;
import sun.reflect.annotation.AnnotationType;
@@ -50,6 +51,11 @@
AnnotationType getAnnotationType(Class<?> klass);
/**
+ * Get the declared annotations for a given class, indexed by their types.
+ */
+ Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass);
+
+ /**
* Get the array of bytes that is the class-file representation
* of this Class' annotations.
*/
diff --git a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index f9200bb..e12abb1 100644
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -903,6 +903,18 @@
private String getHostAndPort(URL url) {
String host = url.getHost();
+ final String hostarg = host;
+ try {
+ // lookup hostname and use IP address if available
+ host = AccessController.doPrivileged(
+ new PrivilegedExceptionAction<String>() {
+ public String run() throws IOException {
+ InetAddress addr = InetAddress.getByName(hostarg);
+ return addr.getHostAddress();
+ }
+ }
+ );
+ } catch (PrivilegedActionException e) {}
int port = url.getPort();
if (port == -1) {
String scheme = url.getProtocol();
diff --git a/src/share/classes/sun/nio/ch/FileChannelImpl.java b/src/share/classes/sun/nio/ch/FileChannelImpl.java
index b464ecc..3c4ddaa 100644
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java
@@ -840,7 +840,15 @@
ti = threads.add();
if (!isOpen())
return null;
- if (size() < position + size) { // Extend file size
+
+ long filesize;
+ do {
+ filesize = nd.size(fd);
+ } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+
+ if (filesize < position + size) { // Extend file size
if (!writable) {
throw new IOException("Channel not open for writing " +
"- cannot extend file to required size");
@@ -849,6 +857,8 @@
do {
rv = nd.truncate(fd, position + size);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
}
if (size == 0) {
addr = 0;
diff --git a/src/share/classes/sun/nio/cs/ext/DoubleByte.java b/src/share/classes/sun/nio/cs/ext/DoubleByte.java
index c213d28..398ab52 100644
--- a/src/share/classes/sun/nio/cs/ext/DoubleByte.java
+++ b/src/share/classes/sun/nio/cs/ext/DoubleByte.java
@@ -111,7 +111,6 @@
public static class Decoder extends CharsetDecoder
implements DelegatableDecoder, ArrayDecoder
{
-
final char[][] b2c;
final char[] b2cSB;
final int b2Min;
@@ -122,7 +121,12 @@
return CoderResult.UNDERFLOW;
}
- protected CoderResult crMalformedOrUnmappable(int b) {
+ protected CoderResult crMalformedOrUnmappable(int b1, int b2) {
+ if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte(b1)
+ b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte(b2)
+ decodeSingle(b2) != UNMAPPABLE_DECODING) { // isSingle(b2)
+ return CoderResult.malformedForLength(1);
+ }
return CoderResult.unmappableForLength(2);
}
@@ -161,7 +165,7 @@
int b2 = sa[sp + 1] & 0xff;
if (b2 < b2Min || b2 > b2Max ||
(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
- return crMalformedOrUnmappable(b1);
+ return crMalformedOrUnmappable(b1, b2);
}
inSize++;
}
@@ -190,7 +194,7 @@
int b2 = src.get() & 0xff;
if (b2 < b2Min || b2 > b2Max ||
(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING)
- return crMalformedOrUnmappable(b1);
+ return crMalformedOrUnmappable(b1, b2);
inSize++;
}
dst.put(c);
@@ -221,8 +225,13 @@
if (c == UNMAPPABLE_DECODING) {
if (sp < sl) {
int b2 = src[sp++] & 0xff;
- if (b2 >= b2Min && b2 <= b2Max) {
- c = b2c[b1][b2 - b2Min];
+ if (b2 < b2Min || b2 > b2Max ||
+ (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
+ if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte
+ b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte
+ decodeSingle(b2) != UNMAPPABLE_DECODING) {
+ sp--;
+ }
}
}
if (c == UNMAPPABLE_DECODING) {
@@ -466,8 +475,8 @@
return CoderResult.UNDERFLOW;
}
- protected CoderResult crMalformedOrUnmappable(int b) {
- if (b == SS2 || b == SS3 )
+ protected CoderResult crMalformedOrUnmappable(int b1, int b2) {
+ if (b1 == SS2 || b1 == SS3 )
return CoderResult.malformedForLength(1);
return CoderResult.unmappableForLength(2);
}
diff --git a/src/share/classes/sun/nio/fs/Util.java b/src/share/classes/sun/nio/fs/Util.java
index 1fe134f..e9abc6f 100644
--- a/src/share/classes/sun/nio/fs/Util.java
+++ b/src/share/classes/sun/nio/fs/Util.java
@@ -27,6 +27,9 @@
import java.util.*;
import java.nio.file.*;
+import java.nio.charset.Charset;
+import java.security.*;
+import sun.security.action.*;
/**
* Utility methods
@@ -35,6 +38,33 @@
class Util {
private Util() { }
+ private static final Charset jnuEncoding = Charset.forName(
+ AccessController.doPrivileged(new GetPropertyAction("sun.jnu.encoding")));
+
+ /**
+ * Returns {@code Charset} corresponding to the sun.jnu.encoding property
+ */
+ static Charset jnuEncoding() {
+ return jnuEncoding;
+ }
+
+ /**
+ * Encodes the given String into a sequence of bytes using the {@code Charset}
+ * specified by the sun.jnu.encoding property.
+ */
+ static byte[] toBytes(String s) {
+ return s.getBytes(jnuEncoding);
+ }
+
+ /**
+ * Constructs a new String by decoding the specified array of bytes using the
+ * {@code Charset} specified by the sun.jnu.encoding property.
+ */
+ static String toString(byte[] bytes) {
+ return new String(bytes, jnuEncoding);
+ }
+
+
/**
* Splits a string around the given character. The array returned by this
* method contains each substring that is terminated by the character. Use
diff --git a/src/share/classes/sun/reflect/Reflection.java b/src/share/classes/sun/reflect/Reflection.java
index a57b89b..63baa42 100644
--- a/src/share/classes/sun/reflect/Reflection.java
+++ b/src/share/classes/sun/reflect/Reflection.java
@@ -57,6 +57,14 @@
@CallerSensitive
public static native Class<?> getCallerClass();
+ /**
+ * @deprecated This method will be removed in JDK 9.
+ * This method is a private JDK API and retained temporarily for
+ * existing code to run until a replacement API is defined.
+ */
+ @Deprecated
+ public static native Class<?> getCallerClass(int depth);
+
/** Retrieves the access flags written to the class file. For
inner classes these flags may differ from those returned by
Class.getModifiers(), which searches the InnerClasses
diff --git a/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
index 9e01fc5..926d6d0 100644
--- a/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
+++ b/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
@@ -95,6 +95,8 @@
Class<?> clz = (Class)type;
if (clz.getEnclosingClass() == null)
return addTo;
+ if (Modifier.isStatic(clz.getModifiers()))
+ return addNesting(clz.getEnclosingClass(), addTo);
return addNesting(clz.getEnclosingClass(), addTo.pushInner());
} else if (type instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType)type;
@@ -166,7 +168,7 @@
@Override
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotation) {
- return AnnotationSupport.getMultipleAnnotations(annotations, annotation);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation);
}
// AnnotatedType
diff --git a/src/share/classes/sun/reflect/annotation/AnnotationSupport.java b/src/share/classes/sun/reflect/annotation/AnnotationSupport.java
index ed1443a..604e195 100644
--- a/src/share/classes/sun/reflect/annotation/AnnotationSupport.java
+++ b/src/share/classes/sun/reflect/annotation/AnnotationSupport.java
@@ -28,109 +28,212 @@
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+
+import sun.misc.JavaLangAccess;
public final class AnnotationSupport {
+ private static final JavaLangAccess LANG_ACCESS = sun.misc.SharedSecrets.getJavaLangAccess();
+
/**
- * Finds and returns all annotation of the type indicated by
- * {@code annotationClass} from the {@code Map} {@code
- * annotationMap}. Looks into containers of the {@code
- * annotationClass} (as specified by an the {@code
- * annotationClass} type being meta-annotated with an {@code
- * Repeatable} annotation).
+ * Finds and returns all annotations in {@code annotations} matching
+ * the given {@code annoClass}.
*
- * @param annotationMap the {@code Map} used to store annotations indexed by their type
- * @param annotationClass the type of annotation to search for
+ * Apart from annotations directly present in {@code annotations} this
+ * method searches for annotations inside containers i.e. indirectly
+ * present annotations.
*
- * @return an array of instances of {@code annotationClass} or an empty array if none were found
+ * The order of the elements in the array returned depends on the iteration
+ * order of the provided map. Specifically, the directly present annotations
+ * come before the indirectly present annotations if and only if the
+ * directly present annotations come before the indirectly present
+ * annotations in the map.
+ *
+ * @param annotations the {@code Map} in which to search for annotations
+ * @param annoClass the type of annotation to search for
+ *
+ * @return an array of instances of {@code annoClass} or an empty
+ * array if none were found
*/
- public static <A extends Annotation> A[] getMultipleAnnotations(
- final Map<Class<? extends Annotation>, Annotation> annotationMap,
- final Class<A> annotationClass) {
- final List<A> res = new ArrayList<A>();
+ public static <A extends Annotation> A[] getDirectlyAndIndirectlyPresent(
+ Map<Class<? extends Annotation>, Annotation> annotations,
+ Class<A> annoClass) {
+ List<A> result = new ArrayList<A>();
@SuppressWarnings("unchecked")
- final A candidate = (A)annotationMap.get(annotationClass);
- if (candidate != null) {
- res.add(candidate);
+ A direct = (A) annotations.get(annoClass);
+ if (direct != null)
+ result.add(direct);
+
+ A[] indirect = getIndirectlyPresent(annotations, annoClass);
+ if (indirect != null && indirect.length != 0) {
+ boolean indirectFirst = direct == null ||
+ containerBeforeContainee(annotations, annoClass);
+
+ result.addAll((indirectFirst ? 0 : 1), Arrays.asList(indirect));
}
- final Class<? extends Annotation> containerClass = getContainer(annotationClass);
- if (containerClass != null) {
- res.addAll(unpackAll(annotationMap.get(containerClass), annotationClass));
- }
-
- @SuppressWarnings("unchecked") // should be safe annotationClass is a token for A
- final A[] emptyTemplateArray = (A[])Array.newInstance(annotationClass, 0);
- return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
+ @SuppressWarnings("unchecked")
+ A[] arr = (A[]) Array.newInstance(annoClass, result.size());
+ return result.toArray(arr);
}
- /** Helper to get the container, or null if none, of an annotation. */
- private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
- Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
- return (containingAnnotation == null) ? null : containingAnnotation.value();
- }
-
- /** Reflectively look up and get the returned array from the the
- * invocation of the value() element on an instance of an
- * Annotation.
+ /**
+ * Finds and returns all annotations matching the given {@code annoClass}
+ * indirectly present in {@code annotations}.
+ *
+ * @param annotations annotations to search indexed by their types
+ * @param annoClass the type of annotation to search for
+ *
+ * @return an array of instances of {@code annoClass} or an empty array if no
+ * indirectly present annotations were found
*/
- private static <A extends Annotation> A[] getValueArray(Annotation containerInstance) {
- try {
- // the spec tells us the container must have an array-valued
- // value element. Get the AnnotationType, get the "value" element
- // and invoke it to get the contents.
+ private static <A extends Annotation> A[] getIndirectlyPresent(
+ Map<Class<? extends Annotation>, Annotation> annotations,
+ Class<A> annoClass) {
- Class<? extends Annotation> containerClass = containerInstance.annotationType();
+ Repeatable repeatable = annoClass.getDeclaredAnnotation(Repeatable.class);
+ if (repeatable == null)
+ return null; // Not repeatable -> no indirectly present annotations
+
+ Class<? extends Annotation> containerClass = repeatable.value();
+
+ Annotation container = annotations.get(containerClass);
+ if (container == null)
+ return null;
+
+ // Unpack container
+ A[] valueArray = getValueArray(container);
+ checkTypes(valueArray, container, annoClass);
+
+ return valueArray;
+ }
+
+
+ /**
+ * Figures out if conatiner class comes before containee class among the
+ * keys of the given map.
+ *
+ * @return true if container class is found before containee class when
+ * iterating over annotations.keySet().
+ */
+ private static <A extends Annotation> boolean containerBeforeContainee(
+ Map<Class<? extends Annotation>, Annotation> annotations,
+ Class<A> annoClass) {
+
+ Class<? extends Annotation> containerClass =
+ annoClass.getDeclaredAnnotation(Repeatable.class).value();
+
+ for (Class<? extends Annotation> c : annotations.keySet()) {
+ if (c == containerClass) return true;
+ if (c == annoClass) return false;
+ }
+
+ // Neither containee nor container present
+ return false;
+ }
+
+
+ /**
+ * Finds and returns all associated annotations matching the given class.
+ *
+ * The order of the elements in the array returned depends on the iteration
+ * order of the provided maps. Specifically, the directly present annotations
+ * come before the indirectly present annotations if and only if the
+ * directly present annotations come before the indirectly present
+ * annotations in the relevant map.
+ *
+ * @param declaredAnnotations the declared annotations indexed by their types
+ * @param decl the class declaration on which to search for annotations
+ * @param annoClass the type of annotation to search for
+ *
+ * @return an array of instances of {@code annoClass} or an empty array if none were found.
+ */
+ public static <A extends Annotation> A[] getAssociatedAnnotations(
+ Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
+ Class<?> decl,
+ Class<A> annoClass) {
+ Objects.requireNonNull(decl);
+
+ // Search declared
+ A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
+
+ // Search inherited
+ if(AnnotationType.getInstance(annoClass).isInherited()) {
+ Class<?> superDecl = decl.getSuperclass();
+ while (result.length == 0 && superDecl != null) {
+ result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
+ superDecl = superDecl.getSuperclass();
+ }
+ }
+
+ return result;
+ }
+
+
+ /* Reflectively invoke the values-method of the given annotation
+ * (container), cast it to an array of annotations and return the result.
+ */
+ private static <A extends Annotation> A[] getValueArray(Annotation container) {
+ try {
+ // According to JLS the container must have an array-valued value
+ // method. Get the AnnotationType, get the "value" method and invoke
+ // it to get the content.
+
+ Class<? extends Annotation> containerClass = container.annotationType();
AnnotationType annoType = AnnotationType.getInstance(containerClass);
if (annoType == null)
- throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations");
+ throw invalidContainerException(container, null);
Method m = annoType.members().get("value");
if (m == null)
- throw new AnnotationFormatError(containerInstance +
- " is an invalid container for repeating annotations");
+ throw invalidContainerException(container, null);
+
m.setAccessible(true);
- @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
- A[] a = (A[])m.invoke(containerInstance); // this will erase to (Annotation[]) but we
- // do a runtime cast on the return-value
- // in the methods that call this method
- return a;
- } catch (IllegalAccessException | // couldnt loosen security
- IllegalArgumentException | // parameters doesn't match
+ // This will erase to (Annotation[]) but we do a runtime cast on the
+ // return-value in the method that call this method.
+ @SuppressWarnings("unchecked")
+ A[] values = (A[]) m.invoke(container);
+
+ return values;
+
+ } catch (IllegalAccessException | // couldn't loosen security
+ IllegalArgumentException | // parameters doesn't match
InvocationTargetException | // the value method threw an exception
- ClassCastException e) { // well, a cast failed ...
- throw new AnnotationFormatError(
- containerInstance + " is an invalid container for repeating annotations",
- e);
+ ClassCastException e) {
+
+ throw invalidContainerException(container, e);
+
}
}
- /* Sanity check type of and return a list of all the annotation
- * instances of type {@code annotationClass} from {@code
- * containerInstance}.
- */
- private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
- Class<A> annotationClass) {
- if (containerInstance == null) {
- return Collections.emptyList(); // container not present
- }
- try {
- A[] a = getValueArray(containerInstance);
- List<A> l = new ArrayList<>(a.length);
- for (int i = 0; i < a.length; i++)
- l.add(annotationClass.cast(a[i]));
- return l;
- } catch (ClassCastException |
- NullPointerException e) {
- throw new AnnotationFormatError(
- String.format("%s is an invalid container for repeating annotations of type: %s",
- containerInstance, annotationClass),
- e);
+ private static AnnotationFormatError invalidContainerException(Annotation anno,
+ Throwable cause) {
+ return new AnnotationFormatError(
+ anno + " is an invalid container for repeating annotations",
+ cause);
+ }
+
+
+ /* Sanity check type of all the annotation instances of type {@code annoClass}
+ * from {@code container}.
+ */
+ private static <A extends Annotation> void checkTypes(A[] annotations,
+ Annotation container,
+ Class<A> annoClass) {
+ for (A a : annotations) {
+ if (!annoClass.isInstance(a)) {
+ throw new AnnotationFormatError(
+ String.format("%s is an invalid container for " +
+ "repeating annotations of type: %s",
+ container, annoClass));
+ }
}
}
}
diff --git a/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
index bcf48ff..d716a47 100644
--- a/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
+++ b/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java
@@ -54,7 +54,7 @@
*
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
* @param cp the ConstantPool needed to parse the embedded Annotation
- * @param decl the dclaration this type annotation is on
+ * @param decl the declaration this type annotation is on
* @param container the Class this type annotation is on (may be the same as decl)
* @param type the type the AnnotatedType corresponds to
* @param filter the type annotation targets included in this AnnotatedType
diff --git a/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
index 63da5ea..58a3070 100644
--- a/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
+++ b/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
@@ -198,7 +198,7 @@
@Override
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
}
@Override
diff --git a/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java b/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java
index e77e224..da819be 100644
--- a/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java
+++ b/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java
@@ -34,6 +34,7 @@
import sun.rmi.runtime.NewThreadAction;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetLongAction;
+import sun.security.action.GetPropertyAction;
/**
* RMIMasterSocketFactory attempts to create a socket connection to the
@@ -103,22 +104,21 @@
try {
String proxyHost;
proxyHost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.proxyHost"));
+ new GetPropertyAction("http.proxyHost"));
if (proxyHost == null)
proxyHost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("proxyHost"));
+ new GetPropertyAction("proxyHost"));
- Boolean tmp = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("java.rmi.server.disableHttp"));
+ boolean disable = java.security.AccessController.doPrivileged(
+ new GetPropertyAction("java.rmi.server.disableHttp", "true"))
+ .equalsIgnoreCase("true");
- if (!tmp.booleanValue() &&
- (proxyHost != null && proxyHost.length() > 0)) {
+ if (!disable && proxyHost != null && proxyHost.length() > 0) {
setFactories = true;
}
} catch (Exception e) {
- // unable to obtain the properties, so assume default behavior.
- setFactories = true;
+ // unable to obtain the properties, so use the default behavior.
}
if (setFactories) {
diff --git a/src/share/classes/sun/security/provider/certpath/RevocationChecker.java b/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
index 0aad090..f34e737 100644
--- a/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
+++ b/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
@@ -307,7 +307,7 @@
: anchor.getCAPublicKey();
}
crlSignFlag = true;
- if (params.certPath() != null) {
+ if (params != null && params.certPath() != null) {
certIndex = params.certPath().getCertificates().size() - 1;
} else {
certIndex = -1;
diff --git a/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java b/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
index 397a859..7c522ba 100644
--- a/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
+++ b/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
@@ -79,7 +79,7 @@
{".verbose.suboptions.verbose.output.when.signing.verifying.",
"[-verbose[:suboptions]] \u7F72\u540D/\u691C\u8A3C\u6642\u306E\u8A73\u7D30\u51FA\u529B\u3002"},
{".suboptions.can.be.all.grouped.or.summary",
- " \u30B5\u30D6\u30AA\u30D7\u30B7\u30E7\u30F3\u3068\u3057\u3066\u3001\u3059\u3079\u3066\u3001\u30B0\u30EB\u30FC\u30D7\u307E\u305F\u306F\u30B5\u30DE\u30EA\u30FC\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059"},
+ " \u30B5\u30D6\u30AA\u30D7\u30B7\u30E7\u30F3\u3068\u3057\u3066\u3001all\u3001grouped\u307E\u305F\u306Fsummary\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059"},
{".certs.display.certificates.when.verbose.and.verifying",
"[-certs] \u8A73\u7D30\u51FA\u529B\u304A\u3088\u3073\u691C\u8A3C\u6642\u306B\u8A3C\u660E\u66F8\u3092\u8868\u793A"},
{".tsa.url.location.of.the.Timestamping.Authority",
diff --git a/src/share/classes/sun/security/tools/policytool/PolicyTool.java b/src/share/classes/sun/security/tools/policytool/PolicyTool.java
index bfc91e4..87cdc26 100644
--- a/src/share/classes/sun/security/tools/policytool/PolicyTool.java
+++ b/src/share/classes/sun/security/tools/policytool/PolicyTool.java
@@ -1092,19 +1092,19 @@
JMenu menu = new JMenu();
configureButton(menu, "File");
ActionListener actionListener = new FileMenuListener(tool, this);
- addMenuItem(menu, NEW_POLICY_FILE, actionListener);
- addMenuItem(menu, OPEN_POLICY_FILE, actionListener);
- addMenuItem(menu, SAVE_POLICY_FILE, actionListener);
- addMenuItem(menu, SAVE_AS_POLICY_FILE, actionListener);
- addMenuItem(menu, VIEW_WARNINGS, actionListener);
- addMenuItem(menu, QUIT, actionListener);
+ addMenuItem(menu, NEW_POLICY_FILE, actionListener, "N");
+ addMenuItem(menu, OPEN_POLICY_FILE, actionListener, "O");
+ addMenuItem(menu, SAVE_POLICY_FILE, actionListener, "S");
+ addMenuItem(menu, SAVE_AS_POLICY_FILE, actionListener, null);
+ addMenuItem(menu, VIEW_WARNINGS, actionListener, null);
+ addMenuItem(menu, QUIT, actionListener, null);
menuBar.add(menu);
// create a KeyStore menu
menu = new JMenu();
configureButton(menu, "KeyStore");
actionListener = new MainWindowListener(tool, this);
- addMenuItem(menu, EDIT_KEYSTORE, actionListener);
+ addMenuItem(menu, EDIT_KEYSTORE, actionListener, null);
menuBar.add(menu);
setJMenuBar(menuBar);
@@ -1220,23 +1220,24 @@
// Platform specific modifier (control / command).
private int shortCutModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- private void addMenuItem(JMenu menu, String key, ActionListener actionListener) {
+ private void addMenuItem(JMenu menu, String key, ActionListener actionListener, String accelerator) {
JMenuItem menuItem = new JMenuItem();
configureButton(menuItem, key);
if (PolicyTool.rb.containsKey(key + ".accelerator")) {
- String accelerator = PolicyTool.getMessage(key + ".accelerator");
- if (accelerator != null && !accelerator.isEmpty()) {
- KeyStroke keyStroke;
- if (accelerator.matches("^control .$")) {
- // Map "control" key to "command" on MacOS
- keyStroke = KeyStroke.getKeyStroke(KeyEvent.getExtendedKeyCodeForChar(accelerator.charAt(8)),
- shortCutModifier);
- } else {
- keyStroke = KeyStroke.getKeyStroke(accelerator);
- }
- menuItem.setAccelerator(keyStroke);
+ // Accelerator from resources takes precedence
+ accelerator = PolicyTool.getMessage(key + ".accelerator");
+ }
+
+ if (accelerator != null && !accelerator.isEmpty()) {
+ KeyStroke keyStroke;
+ if (accelerator.length() == 1) {
+ keyStroke = KeyStroke.getKeyStroke(KeyEvent.getExtendedKeyCodeForChar(accelerator.charAt(0)),
+ shortCutModifier);
+ } else {
+ keyStroke = KeyStroke.getKeyStroke(accelerator);
}
+ menuItem.setAccelerator(keyStroke);
}
menuItem.addActionListener(actionListener);
diff --git a/src/share/classes/sun/security/tools/policytool/Resources.java b/src/share/classes/sun/security/tools/policytool/Resources.java
index 82c53b3..5fffebe 100644
--- a/src/share/classes/sun/security/tools/policytool/Resources.java
+++ b/src/share/classes/sun/security/tools/policytool/Resources.java
@@ -45,11 +45,8 @@
{".file.file.policy.file.location",
" [-file <file>] policy file location"},
{"New", "&New"},
- {"New.accelerator", "control N"},
{"Open", "&Open..."},
- {"Open.accelerator", "control O"},
{"Save", "&Save"},
- {"Save.accelerator", "control S"},
{"Save.As", "Save &As..."},
{"View.Warning.Log", "View &Warning Log"},
{"Exit", "E&xit"},
@@ -92,8 +89,6 @@
{"OK.to.overwrite.existing.file.filename.",
"OK to overwrite existing file {0}?"},
{"Cancel", "Cancel"},
-
- // Policy Entry Dialog
{"CodeBase.", "&CodeBase:"},
{"SignedBy.", "&SignedBy:"},
{"Add.Principal", "&Add Principal"},
@@ -104,13 +99,10 @@
{".Edit.Permission", " Ed&it Permission"},
{"Remove.Permission", "Re&move Permission"},
{"Done", "Done"},
-
- // KeyStore Edit Dialog
{"KeyStore.URL.", "KeyStore &URL:"},
{"KeyStore.Type.", "KeyStore &Type:"},
{"KeyStore.Provider.", "KeyStore &Provider:"},
{"KeyStore.Password.URL.", "KeyStore Pass&word URL:"},
-
{"Principals", "Principals"},
{".Edit.Principal.", " Edit Principal:"},
{".Add.New.Principal.", " Add New Principal:"},
diff --git a/src/share/classes/sun/tools/jar/Main.java b/src/share/classes/sun/tools/jar/Main.java
index dd5b4bc..7a3e395 100644
--- a/src/share/classes/sun/tools/jar/Main.java
+++ b/src/share/classes/sun/tools/jar/Main.java
@@ -31,6 +31,7 @@
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;
+import java.util.jar.Pack200.*;
import java.util.jar.Manifest;
import java.text.MessageFormat;
import sun.misc.JarIndex;
@@ -72,8 +73,9 @@
* flag0: no zip compression (store only)
* Mflag: DO NOT generate a manifest file (just ZIP)
* iflag: generate jar index
+ * nflag: Perform jar normalization at the end
*/
- boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag;
+ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag;
static final String MANIFEST_DIR = "META-INF/";
static final String VERSION = "1.0";
@@ -197,12 +199,56 @@
vflag = false;
}
}
+ File tmpfile = null;
+ final OutputStream finalout = out;
+ final String tmpbase = (fname == null)
+ ? "tmpjar"
+ : fname.substring(fname.indexOf(File.separatorChar) + 1);
+ if (nflag) {
+ tmpfile = createTemporaryFile(tmpbase, ".jar");
+ out = new FileOutputStream(tmpfile);
+ }
expand(null, files, false);
create(new BufferedOutputStream(out, 4096), manifest);
if (in != null) {
in.close();
}
out.close();
+ if(nflag) {
+ JarFile jarFile = null;
+ File packFile = null;
+ JarOutputStream jos = null;
+ try {
+ Packer packer = Pack200.newPacker();
+ Map<String, String> p = packer.properties();
+ p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
+ jarFile = new JarFile(tmpfile.getCanonicalPath());
+ packFile = createTemporaryFile(tmpbase, ".pack");
+ out = new FileOutputStream(packFile);
+ packer.pack(jarFile, out);
+ jos = new JarOutputStream(finalout);
+ Unpacker unpacker = Pack200.newUnpacker();
+ unpacker.unpack(packFile, jos);
+ } catch (IOException ioe) {
+ fatalError(ioe);
+ } finally {
+ if (jarFile != null) {
+ jarFile.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (jos != null) {
+ jos.close();
+ }
+ if (tmpfile != null && tmpfile.exists()) {
+ tmpfile.delete();
+ }
+ if (packFile != null && packFile.exists()) {
+ packFile.delete();
+ }
+ }
+ }
} else if (uflag) {
File inputFile = null, tmpFile = null;
FileInputStream in;
@@ -358,6 +404,9 @@
rootjar = args[count++];
iflag = true;
break;
+ case 'n':
+ nflag = true;
+ break;
case 'e':
ename = args[count++];
break;
@@ -1215,4 +1264,34 @@
e.setCrc(crc.getValue());
}
}
+
+ /**
+ * Attempt to create temporary file in the system-provided temporary folder, if failed attempts
+ * to create it in the same folder as the file in parameter (if any)
+ */
+ private File createTemporaryFile(String tmpbase, String suffix) {
+ File tmpfile = null;
+
+ try {
+ tmpfile = File.createTempFile(tmpbase, suffix);
+ } catch (IOException | SecurityException e) {
+ // Unable to create file due to permission violation or security exception
+ }
+ if (tmpfile == null) {
+ // Were unable to create temporary file, fall back to temporary file in the same folder
+ if (fname != null) {
+ try {
+ File tmpfolder = new File(fname).getAbsoluteFile().getParentFile();
+ tmpfile = File.createTempFile(fname, ".tmp" + suffix, tmpfolder);
+ } catch (IOException ioe) {
+ // Last option failed - fall gracefully
+ fatalError(ioe);
+ }
+ } else {
+ // No options left - we can not compress to stdout without access to the temporary folder
+ fatalError(new IOException(getMsg("error.create.tempfile")));
+ }
+ }
+ return tmpfile;
+ }
}
diff --git a/src/share/classes/sun/tools/jar/resources/jar.properties b/src/share/classes/sun/tools/jar/resources/jar.properties
index c8e8d9a..b8b07ce 100644
--- a/src/share/classes/sun/tools/jar/resources/jar.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar.properties
@@ -44,6 +44,8 @@
{0} : could not create directory
error.incorrect.length=\
incorrect length while processing: {0}
+error.create.tempfile=\
+ Could not create a temporary file
out.added.manifest=\
added manifest
out.update.manifest=\
@@ -66,7 +68,7 @@
(in = {0}) (out= {1})
usage=\
-Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
+Usage: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
Options:\n\
\ \ -c create new archive\n\
\ \ -t list table of contents for archive\n\
@@ -75,6 +77,7 @@
\ \ -v generate verbose output on standard output\n\
\ \ -f specify archive file name\n\
\ \ -m include manifest information from specified manifest file\n\
+\ \ -n perform Pack200 normalization after creating a new archive\n\
\ \ -e specify application entry point for stand-alone application \n\
\ \ bundled into an executable jar file\n\
\ \ -0 store only; use no ZIP compression\n\
diff --git a/src/share/classes/sun/tools/jar/resources/jar_es.properties b/src/share/classes/sun/tools/jar/resources/jar_es.properties
index e5ce11b..39e71f8 100644
--- a/src/share/classes/sun/tools/jar/resources/jar_es.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar_es.properties
@@ -44,4 +44,4 @@
out.inflated=\ inflado: {0}
out.size=(entrada = {0}) (salida = {1})
-usage=Sintaxis: jar {ctxui}[vfm0Me] [archive-jar] [archive-manifiesto] [punto-entrada] [-C dir] archivos...\nOpciones:\n -c crear nuevo archivo\n -t crear la tabla de contenido del archivo\n -x extraer el archive mencionado (o todos) del archivo\n -u actualizar archive existente\n -v generar salida detallada de los datos de salida est\u00E1ndar\n -f especificar nombre de archive de almacenamiento\n -m incluir informaci\u00F3n de manifiesto del archive de manifiesto especificado\n -e especificar punto de entrada de la aplicaci\u00F3n para la aplicaci\u00F3n aut\u00F3noma \n que se incluye dentro de un archive jar ejecutable\n -0 s\u00F3lo almacenar; no utilizar compresi\u00F3n ZIP\n -M no crear un archive de manifiesto para las entradas\n -i generar informaci\u00F3n de \u00EDndice para los archives jar especificados\n -C cambiar al directorio especificado e incluir el archivo siguiente\nSi alg\u00FAn archivo es un directorio, se procesar\u00E1 de forma recurrente.\nEl nombre del archivo de manifiesto, el nombre del archivo de almacenamiento y el nombre del punto de entrada se\nespecifican en el mismo orden que los indicadores 'm', 'f' y 'e'.\n\nEjemplo 1: para archivar archivos de dos clases en un archivo llamado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEjemplo 2: utilice un archivo de manifiesto existente 'mymanifest' y archive todos los\n archivos del directorio foo/ en 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
+usage=Sintaxis: jar {ctxui}[vfm0Me] [archive-jar] [archive-manifiesto] [punto-entrada] [-C dir] archivos...\nOpciones:\n -c crear nuevo archivo\n -t crear la tabla de contenido del archivo\n -x extraer el archive mencionado (o todos) del archivo\n -u actualizar archive existente\n -v generar salida detallada de los datos de salida est\u00E1ndar\n -f especificar nombre de archive de almacenamiento\n -m incluir informaci\u00F3n de manifiesto del archive de manifiesto especificado\n -e especificar punto de entrada de la aplicaci\u00F3n para la aplicaci\u00F3n aut\u00F3noma \n que se incluye dentro de un archive jar ejecutable\n -0 s\u00F3lo almacenar; no utilizar compresi\u00F3n ZIP\n -M no crear un archive de manifiesto para las entradas\n -i generar informaci\u00F3n de \u00EDndice para los archives jar especificados\n -C cambiar al directorio especificado e incluir el archivo siguiente\nSi alg\u00FAn archivo es un directorio, se procesar\u00E1 de forma recurrente.\nEl nombre del archivo de manifiesto, el nombre del archivo de almacenamiento y el nombre del punto de entrada se\nespecifican en el mismo orden que los indicadores 'm', 'f' y 'e'.\n\nEjemplo 1: para archivar archivos de dos clases en un archivo llamado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEjemplo 2: utilice un archivo de manifiesto existente 'mymanifest' y archive todos los\n archivos del directorio foo/ en 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
diff --git a/src/share/classes/sun/tools/jar/resources/jar_it.properties b/src/share/classes/sun/tools/jar/resources/jar_it.properties
index 50652a8..54099b7 100644
--- a/src/share/classes/sun/tools/jar/resources/jar_it.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar_it.properties
@@ -44,4 +44,4 @@
out.inflated=\ decompresso: {0}
out.size=(in = {0}) (out = {1})
-usage=Uso: jar {ctxui}[vfm0Me] [file-jar] [file-manifest] [punto di ingresso] [-C dir] file ...\nOpzioni:\n -c crea un nuovo archivio\n -t visualizza l'indice dell'archivio\n -x estrae i file con nome (o tutti i file) dall'archivio\n -u aggiorna l'archivio esistente\n -v genera output commentato dall'output standard\n -f specifica il nome file dell'archivio\n -m include informazioni manifest dal file manifest specificato\n -e specifica il punto di ingresso per l'applicazione stand-alone \n inclusa nel file jar eseguibile\n -0 solo memorizzazione; senza compressione ZIP\n -M consente di non creare un file manifest per le voci\n -i genera informazioni sull'indice per i file jar specificati\n -C imposta la directory specificata e include il file seguente\nSe un file \u00E8 una directory, verr\u00E0 elaborato in modo ricorsivo.\nIl nome del file manifest, del file di archivio e del punto di ingresso devono\nessere specificati nello stesso ordine dei flag 'm', 'f' ed 'e'.\n\nEsempio 1: archiviazione di due file di classe in un archivio con il nome classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEsempio 2: utilizzo del file manifest esistente 'mymanifest' e archiviazione di tutti i\n file della directory foo/ in 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/.\n
+usage=Uso: jar {ctxui}[vfm0Me] [file-jar] [file-manifest] [punto di ingresso] [-C dir] file ...\nOpzioni:\n -c crea un nuovo archivio\n -t visualizza l'indice dell'archivio\n -x estrae i file con nome (o tutti i file) dall'archivio\n -u aggiorna l'archivio esistente\n -v genera output commentato dall'output standard\n -f specifica il nome file dell'archivio\n -m include informazioni manifest dal file manifest specificato\n -e specifica il punto di ingresso per l'applicazione stand-alone \n inclusa nel file jar eseguibile\n -0 solo memorizzazione; senza compressione ZIP\n -M consente di non creare un file manifest per le voci\n -i genera informazioni sull'indice per i file jar specificati\n -C imposta la directory specificata e include il file seguente\nSe un file \u00E8 una directory, verr\u00E0 elaborato in modo ricorsivo.\nIl nome del file manifest, del file di archivio e del punto di ingresso devono\nessere specificati nello stesso ordine dei flag 'm', 'f' ed 'e'.\n\nEsempio 1: archiviazione di due file di classe in un archivio con il nome classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEsempio 2: utilizzo del file manifest esistente 'mymanifest' e archiviazione di tutti i\n file della directory foo/ in 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
diff --git a/src/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/share/classes/sun/tools/jar/resources/jar_ja.properties
index 7167ef1..0a1457e 100644
--- a/src/share/classes/sun/tools/jar/resources/jar_ja.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar_ja.properties
@@ -44,4 +44,4 @@
out.inflated=\ {0}\u304C\u5C55\u958B\u3055\u308C\u307E\u3057\u305F
out.size=(\u5165={0})(\u51FA={1})
-usage=\u4F7F\u7528\u65B9\u6CD5: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u30AA\u30D7\u30B7\u30E7\u30F3:\n -c \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u65B0\u898F\u4F5C\u6210\u3059\u308B\n -t \u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u4E00\u89A7\u8868\u793A\u3059\u308B\n -x \u6307\u5B9A\u306E(\u307E\u305F\u306F\u3059\u3079\u3066\u306E)\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u62BD\u51FA\u3059\u308B\n -u \u65E2\u5B58\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u66F4\u65B0\u3059\u308B\n -v \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n -f \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3059\u308B\n -m \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\u53D6\u308A\u8FBC\u3080\n -e \u5B9F\u884C\u53EF\u80FDjar\u30D5\u30A1\u30A4\u30EB\u306B\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\n \u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\u3059\u308B\n -0 \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u306A\u3044\n -M \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u306A\u3044\n -i \u6307\u5B9A\u306Ejar\u30D5\u30A1\u30A4\u30EB\u306E\u7D22\u5F15\u60C5\u5831\u3092\u751F\u6210\u3059\u308B\n -C \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u4EE5\u4E0B\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u308A\u8FBC\u3080\n\u30D5\u30A1\u30A4\u30EB\u304C\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u5834\u5408\u306F\u518D\u5E30\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\n\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3001\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u304A\u3088\u3073\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u540D\u306F\u3001\n\u30D5\u30E9\u30B0'm'\u3001'f'\u3001'e'\u306E\u6307\u5B9A\u3068\u540C\u3058\u9806\u756A\u3067\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u4F8B1: 2\u3064\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6classes.jar\u306B\u4FDD\u5B58\u3059\u308B:\n jar cvf classes.jar Foo.class Bar.class\n\u4F8B2: \u65E2\u5B58\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB'mymanifest'\u3092\u4F7F\u7528\u3057\u3001foo/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\n \u5168\u30D5\u30A1\u30A4\u30EB\u3092'classes.jar'\u306B\u30A2\u30FC\u30AB\u30A4\u30D6\u3059\u308B:\n jar cvfm classes.jar mymanifest -C foo/ \n
+usage=\u4F7F\u7528\u65B9\u6CD5: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u30AA\u30D7\u30B7\u30E7\u30F3:\n -c \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u65B0\u898F\u4F5C\u6210\u3059\u308B\n -t \u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u4E00\u89A7\u8868\u793A\u3059\u308B\n -x \u6307\u5B9A\u306E(\u307E\u305F\u306F\u3059\u3079\u3066\u306E)\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u62BD\u51FA\u3059\u308B\n -u \u65E2\u5B58\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u66F4\u65B0\u3059\u308B\n -v \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n -f \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3059\u308B\n -m \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\u53D6\u308A\u8FBC\u3080\n -e \u5B9F\u884C\u53EF\u80FDjar\u30D5\u30A1\u30A4\u30EB\u306B\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\n \u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\u3059\u308B\n -0 \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u306A\u3044\n -M \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u306A\u3044\n -i \u6307\u5B9A\u306Ejar\u30D5\u30A1\u30A4\u30EB\u306E\u7D22\u5F15\u60C5\u5831\u3092\u751F\u6210\u3059\u308B\n -C \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u4EE5\u4E0B\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u308A\u8FBC\u3080\n\u30D5\u30A1\u30A4\u30EB\u304C\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u5834\u5408\u306F\u518D\u5E30\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\n\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3001\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u304A\u3088\u3073\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u540D\u306F\u3001\n\u30D5\u30E9\u30B0'm'\u3001'f'\u3001'e'\u306E\u6307\u5B9A\u3068\u540C\u3058\u9806\u756A\u3067\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u4F8B1: 2\u3064\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6classes.jar\u306B\u4FDD\u5B58\u3059\u308B:\n jar cvf classes.jar Foo.class Bar.class\n\u4F8B2: \u65E2\u5B58\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB'mymanifest'\u3092\u4F7F\u7528\u3057\u3001foo/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\n \u5168\u30D5\u30A1\u30A4\u30EB\u3092'classes.jar'\u306B\u30A2\u30FC\u30AB\u30A4\u30D6\u3059\u308B:\n jar cvfm classes.jar mymanifest -C foo/ .\n
diff --git a/src/share/classes/sun/tools/jar/resources/jar_sv.properties b/src/share/classes/sun/tools/jar/resources/jar_sv.properties
index a907088..90ca52a 100644
--- a/src/share/classes/sun/tools/jar/resources/jar_sv.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar_sv.properties
@@ -44,4 +44,4 @@
out.inflated=\ uppackat: {0}
out.size=(in = {0}) (ut = {1})
-usage=Syntax: jar {ctxui}[vfm0Me] [jar fil] [manifestfil] [startpunkt] [-C-katalog] ...\nAlternativ:\n -c skapa nytt arkiv\n -t lista inneh\u00E5llsf\u00F6rteckning f\u00F6r arkiv\n -x extrahera namngivna (eller alla) filer fr\u00E5n arkiv\n -u uppdatera befintligt arkiv\n -v generera utf\u00F6rliga utdata vid standardutmatning\n -f ange arkivfilens namn\n -m inkludera manifestinformation fr\u00E5n angivet manifest\n -e ange programstartpunkt f\u00F6r frist\u00E5ende applikation \n som medf\u00F6ljer i en jar-programfil\n -0 endast lagra (ingen zip-komprimering)\n -M skapa inte n\u00E5gon manifestfil f\u00F6r posterna\n -i generera indexinformation f\u00F6r de angivna jar-filerna\n -C \u00E4ndra till den angivna katalogen och inkludera f\u00F6ljande fil\nOm en fil \u00E4r en katalog bearbetas den rekursivt.\nNamnen p\u00E5 manifestfilen, arkivfilen och startpunkten anges i samma\nordning som m-, f- och e-flaggorna.\n\nExempel 1: S\u00E5 h\u00E4r arkiverar du tv\u00E5 klassfiler i ett arkiv med namnet classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExempel 2: Anv\u00E4nd en befintlig manifestfil (mymanifest) och arkivera alla\n filer fr\u00E5n katalogen foo/ i classes.jar: \n jar cvfm classes.jar mymanifest -C foo/ .\n
+usage=Syntax: jar {ctxui}[vfm0Me] [jar-fil] [manifestfil] [startpunkt] [-C katalog] filer...\nAlternativ:\n -c skapa nytt arkiv\n -t lista inneh\u00E5llsf\u00F6rteckning f\u00F6r arkiv\n -x extrahera namngivna (eller alla) filer fr\u00E5n arkiv\n -u uppdatera befintligt arkiv\n -v generera utf\u00F6rliga utdata vid standardutmatning\n -f ange arkivfilens namn\n -m inkludera manifestinformation fr\u00E5n angivet manifest\n -e ange programstartpunkt f\u00F6r frist\u00E5ende applikation \n som medf\u00F6ljer i en jar-programfil\n -0 endast lagra (ingen zip-komprimering)\n -M skapa inte n\u00E5gon manifestfil f\u00F6r posterna\n -i generera indexinformation f\u00F6r de angivna jar-filerna\n -C \u00E4ndra till den angivna katalogen och inkludera f\u00F6ljande fil\nOm en fil \u00E4r en katalog bearbetas den rekursivt.\nNamnen p\u00E5 manifestfilen, arkivfilen och startpunkten anges i samma\nordning som m-, f- och e-flaggorna.\n\nExempel 1: S\u00E5 h\u00E4r arkiverar du tv\u00E5 klassfiler i ett arkiv med namnet classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExempel 2: Anv\u00E4nd en befintlig manifestfil (mymanifest) och arkivera alla\n filer fr\u00E5n katalogen foo/ i classes.jar: \n jar cvfm classes.jar mymanifest -C foo/ .\n
diff --git a/src/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/share/classes/sun/tools/jar/resources/jar_zh_CN.properties
index 2ee8e56..146e06c 100644
--- a/src/share/classes/sun/tools/jar/resources/jar_zh_CN.properties
+++ b/src/share/classes/sun/tools/jar/resources/jar_zh_CN.properties
@@ -44,4 +44,4 @@
out.inflated=\ \u5DF2\u89E3\u538B: {0}
out.size=(\u8F93\u5165 = {0}) (\u8F93\u51FA = {1})
-usage=\u7528\u6CD5: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u9009\u9879\u5305\u62EC: \n -c \u521B\u5EFA\u65B0\u7684\u5F52\u6863\u6587\u4EF6\n -t \u5217\u51FA\u5F52\u6863\u76EE\u5F55\n -x \u4ECE\u6863\u6848\u4E2D\u63D0\u53D6\u6307\u5B9A\u7684 (\u6216\u6240\u6709) \u6587\u4EF6\n -u \u66F4\u65B0\u73B0\u6709\u7684\u5F52\u6863\u6587\u4EF6\n -v \u5728\u6807\u51C6\u8F93\u51FA\u4E2D\u751F\u6210\u8BE6\u7EC6\u8F93\u51FA\n -f \u6307\u5B9A\u5F52\u6863\u6587\u4EF6\u540D\n -m \u5305\u542B\u6307\u5B9A\u6E05\u5355\u6587\u4EF6\u4E2D\u7684\u6E05\u5355\u4FE1\u606F\n -e \u4E3A\u6346\u7ED1\u5230\u53EF\u6267\u884C jar \u6587\u4EF6\u7684\u72EC\u7ACB\u5E94\u7528\u7A0B\u5E8F\n \u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u5165\u53E3\u70B9\n -0 \u4EC5\u5B58\u50A8; \u4E0D\u4F7F\u7528\u60C5\u51B5\u4EFB\u4F55 ZIP \u538B\u7F29\n -M \u4E0D\u521B\u5EFA\u6761\u76EE\u7684\u6E05\u5355\u6587\u4EF6\n -i \u4E3A\u6307\u5B9A\u7684 jar \u6587\u4EF6\u751F\u6210\u7D22\u5F15\u4FE1\u606F\n -C \u66F4\u6539\u4E3A\u6307\u5B9A\u7684\u76EE\u5F55\u5E76\u5305\u542B\u5176\u4E2D\u7684\u6587\u4EF6\n\u5982\u679C\u6709\u4EFB\u4F55\u76EE\u5F55\u6587\u4EF6, \u5219\u5BF9\u5176\u8FDB\u884C\u9012\u5F52\u5904\u7406\u3002\n\u6E05\u5355\u6587\u4EF6\u540D, \u5F52\u6863\u6587\u4EF6\u540D\u548C\u5165\u53E3\u70B9\u540D\u79F0\u7684\u6307\u5B9A\u987A\u5E8F\n\u4E0E 'm', 'f' \u548C 'e' \u6807\u8BB0\u7684\u6307\u5B9A\u987A\u5E8F\u76F8\u540C\u3002\n\n\u793A\u4F8B 1: \u5C06\u4E24\u4E2A\u7C7B\u6587\u4EF6\u5F52\u6863\u5230\u4E00\u4E2A\u540D\u4E3A classes.jar \u7684\u5F52\u6863\u6587\u4EF6\u4E2D: \n jar cvf classes.jar Foo.class Bar.class \n\u793A\u4F8B 2: \u4F7F\u7528\u73B0\u6709\u7684\u6E05\u5355\u6587\u4EF6 'mymanifest' \u5E76\n \u5C06 foo/ \u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u5F52\u6863\u5230 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/\u3002\n
+usage=\u7528\u6CD5: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u9009\u9879\u5305\u62EC: \n -c \u521B\u5EFA\u65B0\u7684\u5F52\u6863\u6587\u4EF6\n -t \u5217\u51FA\u5F52\u6863\u76EE\u5F55\n -x \u4ECE\u6863\u6848\u4E2D\u63D0\u53D6\u6307\u5B9A\u7684 (\u6216\u6240\u6709) \u6587\u4EF6\n -u \u66F4\u65B0\u73B0\u6709\u7684\u5F52\u6863\u6587\u4EF6\n -v \u5728\u6807\u51C6\u8F93\u51FA\u4E2D\u751F\u6210\u8BE6\u7EC6\u8F93\u51FA\n -f \u6307\u5B9A\u5F52\u6863\u6587\u4EF6\u540D\n -m \u5305\u542B\u6307\u5B9A\u6E05\u5355\u6587\u4EF6\u4E2D\u7684\u6E05\u5355\u4FE1\u606F\n -e \u4E3A\u6346\u7ED1\u5230\u53EF\u6267\u884C jar \u6587\u4EF6\u7684\u72EC\u7ACB\u5E94\u7528\u7A0B\u5E8F\n \u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u5165\u53E3\u70B9\n -0 \u4EC5\u5B58\u50A8; \u4E0D\u4F7F\u7528\u60C5\u51B5\u4EFB\u4F55 ZIP \u538B\u7F29\n -M \u4E0D\u521B\u5EFA\u6761\u76EE\u7684\u6E05\u5355\u6587\u4EF6\n -i \u4E3A\u6307\u5B9A\u7684 jar \u6587\u4EF6\u751F\u6210\u7D22\u5F15\u4FE1\u606F\n -C \u66F4\u6539\u4E3A\u6307\u5B9A\u7684\u76EE\u5F55\u5E76\u5305\u542B\u5176\u4E2D\u7684\u6587\u4EF6\n\u5982\u679C\u6709\u4EFB\u4F55\u76EE\u5F55\u6587\u4EF6, \u5219\u5BF9\u5176\u8FDB\u884C\u9012\u5F52\u5904\u7406\u3002\n\u6E05\u5355\u6587\u4EF6\u540D, \u5F52\u6863\u6587\u4EF6\u540D\u548C\u5165\u53E3\u70B9\u540D\u79F0\u7684\u6307\u5B9A\u987A\u5E8F\n\u4E0E 'm', 'f' \u548C 'e' \u6807\u8BB0\u7684\u6307\u5B9A\u987A\u5E8F\u76F8\u540C\u3002\n\n\u793A\u4F8B 1: \u5C06\u4E24\u4E2A\u7C7B\u6587\u4EF6\u5F52\u6863\u5230\u4E00\u4E2A\u540D\u4E3A classes.jar \u7684\u5F52\u6863\u6587\u4EF6\u4E2D: \n jar cvf classes.jar Foo.class Bar.class \n\u793A\u4F8B 2: \u4F7F\u7528\u73B0\u6709\u7684\u6E05\u5355\u6587\u4EF6 'mymanifest' \u5E76\n \u5C06 foo/ \u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u5F52\u6863\u5230 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/ .\n
diff --git a/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/src/share/classes/sun/util/calendar/ZoneInfoFile.java
index 60cd919..d3ca7e9 100644
--- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java
+++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java
@@ -26,6 +26,7 @@
package sun.util.calendar;
import java.io.ByteArrayInputStream;
+import java.io.BufferedInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
@@ -65,8 +66,17 @@
* @return a set of time zone IDs.
*/
public static String[] getZoneIds() {
- String[] ids = Arrays.copyOf(regions, regions.length + oldMappings.length);
+ int len = regions.length + oldMappings.length;
+ if (!USE_OLDMAPPING) {
+ len += 3; // EST/HST/MST not in tzdb.dat
+ }
+ String[] ids = Arrays.copyOf(regions, len);
int i = regions.length;
+ if (!USE_OLDMAPPING) {
+ ids[i++] = "EST";
+ ids[i++] = "HST";
+ ids[i++] = "MST";
+ }
for (int j = 0; j < oldMappings.length; j++) {
ids[i++] = oldMappings[j][0];
}
@@ -243,7 +253,8 @@
try {
String libDir = System.getProperty("java.home") + File.separator + "lib";
try (DataInputStream dis = new DataInputStream(
- new FileInputStream(new File(libDir, "tzdb.dat")))) {
+ new BufferedInputStream(new FileInputStream(
+ new File(libDir, "tzdb.dat"))))) {
load(dis);
}
} catch (Exception x) {
@@ -262,9 +273,17 @@
aliases.put("EST", "America/New_York");
aliases.put("MST", "America/Denver");
aliases.put("HST", "Pacific/Honolulu");
+ } else {
+ zones.put("EST", new ZoneInfo("EST", -18000000));
+ zones.put("MST", new ZoneInfo("MST", -25200000));
+ zones.put("HST", new ZoneInfo("HST", -36000000));
}
}
+ public static boolean useOldMapping() {
+ return USE_OLDMAPPING;
+ }
+
/**
* Loads the rules from a DateInputStream
*
diff --git a/src/share/classes/sun/util/resources/ko/LocaleNames_ko.properties b/src/share/classes/sun/util/resources/ko/LocaleNames_ko.properties
index 861b9fd..a9fee89 100644
--- a/src/share/classes/sun/util/resources/ko/LocaleNames_ko.properties
+++ b/src/share/classes/sun/util/resources/ko/LocaleNames_ko.properties
@@ -1045,7 +1045,7 @@
PN=\ud54f\ucf00\uc5b8 \uc81c\ub3c4
PR=\ud478\uc5d0\ub974\ud1a0\ub9ac\ucf54
PS=\ud314\ub808\uc2a4\ud0c0\uc778
-PT=\ud3ec\ub974\ud2b8\uce7c
+PT=\ud3ec\ub974\ud22c\uce7c
PW=\ud314\ub77c\uc6b0
PY=\ud30c\ub77c\uacfc\uc774
QA=\uce74\ud0c0\ub974
diff --git a/src/share/classes/sun/util/resources/sv/LocaleNames_sv.properties b/src/share/classes/sun/util/resources/sv/LocaleNames_sv.properties
index 96d73a9..e7bd9e0 100644
--- a/src/share/classes/sun/util/resources/sv/LocaleNames_sv.properties
+++ b/src/share/classes/sun/util/resources/sv/LocaleNames_sv.properties
@@ -1106,7 +1106,7 @@
WS=Samoa
YE=Jemen
YT=Mayotte
-ZA=Sydafrika
+ZA=Sydafrika
ZM=Zambia
ZW=Zimbabwe
diff --git a/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java b/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java
index 06f845b..c0519db 100644
--- a/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java
+++ b/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java
@@ -28,6 +28,7 @@
import java.io.*;
import java.util.*;
import java.nio.charset.*;
+import java.util.Map.Entry;
import org.xml.sax.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
@@ -153,11 +154,15 @@
}
synchronized (props) {
- for (String key : props.stringPropertyNames()) {
- Element entry = (Element)properties.appendChild(
- doc.createElement("entry"));
- entry.setAttribute("key", key);
- entry.appendChild(doc.createTextNode(props.getProperty(key)));
+ for (Entry<Object, Object> e : props.entrySet()) {
+ final Object k = e.getKey();
+ final Object v = e.getValue();
+ if (k instanceof String && v instanceof String) {
+ Element entry = (Element)properties.appendChild(
+ doc.createElement("entry"));
+ entry.setAttribute("key", (String)k);
+ entry.appendChild(doc.createTextNode((String)v));
+ }
}
}
emitDocument(doc, os, encoding);
diff --git a/src/share/demo/jfc/Notepad/resources/Notepad_fr.properties b/src/share/demo/jfc/Notepad/resources/Notepad_fr.properties
deleted file mode 100644
index a745b4a..0000000
--- a/src/share/demo/jfc/Notepad/resources/Notepad_fr.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Resource strings for Notepad example
-
-Title=Notepad
-
-# Menu labels
-fileLabel=Fichier
-openLabel=Ouvrir
-newLabel=Nouveau
-saveLabel=Sauver
-exitLabel=Quitter
-
-editLabel=Edition
-cutLabel=Couper
-copyLabel=Copier
-pasteLabel=Coller
-
diff --git a/src/share/demo/jfc/Notepad/resources/Notepad_sv.properties b/src/share/demo/jfc/Notepad/resources/Notepad_sv.properties
deleted file mode 100644
index 3ee04a1..0000000
--- a/src/share/demo/jfc/Notepad/resources/Notepad_sv.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Resource strings for Notepad example
-
-Title=Notepad
-
-# Menu labels
-fileLabel=Arkiv
-openLabel=Öppna
-newLabel=Ny
-saveLabel=Spara
-exitLabel=Avsluta
-
-editLabel=Redigera
-cutLabel=Klippa
-copyLabel=Kopiera
-pasteLabel=Klistra
-
diff --git a/src/share/javavm/export/jvm.h b/src/share/javavm/export/jvm.h
index 754aed6..ff5f823 100644
--- a/src/share/javavm/export/jvm.h
+++ b/src/share/javavm/export/jvm.h
@@ -351,7 +351,7 @@
* java.lang.Class and java.lang.ClassLoader
*/
-#define JVM_DEPTH -1
+#define JVM_CALLER_DEPTH -1
/*
* Returns the immediate caller class of the native method invoking
diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux
index 2c5f5f6..fd49537 100644
--- a/src/share/lib/security/java.security-linux
+++ b/src/share/lib/security/java.security-linux
@@ -183,6 +183,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
@@ -228,6 +229,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx
index 20d5c40..9d19d83 100644
--- a/src/share/lib/security/java.security-macosx
+++ b/src/share/lib/security/java.security-macosx
@@ -184,6 +184,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
@@ -229,6 +230,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris
index a6ce253..ca271d7 100644
--- a/src/share/lib/security/java.security-solaris
+++ b/src/share/lib/security/java.security-solaris
@@ -185,6 +185,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
@@ -229,6 +230,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows
index 1c371f0..8a4cac1 100644
--- a/src/share/lib/security/java.security-windows
+++ b/src/share/lib/security/java.security-windows
@@ -184,6 +184,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
@@ -229,6 +230,7 @@
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
+ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
diff --git a/src/share/native/com/sun/java/util/jar/pack/zip.cpp b/src/share/native/com/sun/java/util/jar/pack/zip.cpp
index 28d51cb..2544091 100644
--- a/src/share/native/com/sun/java/util/jar/pack/zip.cpp
+++ b/src/share/native/com/sun/java/util/jar/pack/zip.cpp
@@ -62,7 +62,7 @@
#endif // End of ZLIB
-#ifdef sparc
+#ifdef _BIG_ENDIAN
#define SWAP_BYTES(a) \
((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
#else
diff --git a/src/share/native/sun/reflect/Reflection.c b/src/share/native/sun/reflect/Reflection.c
index 46cfa57..8da4101 100644
--- a/src/share/native/sun/reflect/Reflection.c
+++ b/src/share/native/sun/reflect/Reflection.c
@@ -26,10 +26,16 @@
#include "jvm.h"
#include "sun_reflect_Reflection.h"
-JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass
+JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__
(JNIEnv *env, jclass unused)
{
- return JVM_GetCallerClass(env, JVM_DEPTH); // JVM_DEPTH is only the expected value
+ return JVM_GetCallerClass(env, JVM_CALLER_DEPTH);
+}
+
+JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__I
+(JNIEnv *env, jclass unused, jint depth)
+{
+ return JVM_GetCallerClass(env, depth);
}
JNIEXPORT jint JNICALL Java_sun_reflect_Reflection_getClassAccessFlags
diff --git a/src/solaris/classes/java/lang/UNIXProcess.java.bsd b/src/solaris/classes/java/lang/UNIXProcess.java.bsd
index b618135..df22bd2 100644
--- a/src/solaris/classes/java/lang/UNIXProcess.java.bsd
+++ b/src/solaris/classes/java/lang/UNIXProcess.java.bsd
@@ -337,40 +337,54 @@
* able to read any buffered data lingering in the OS pipe buffer.
*/
static class ProcessPipeInputStream extends BufferedInputStream {
+ private final Object closeLock = new Object();
+
ProcessPipeInputStream(int fd) {
super(new FileInputStream(newFileDescriptor(fd)));
}
- private static byte[] drainInputStream(InputStream in)
+ private InputStream drainInputStream(InputStream in)
throws IOException {
- if (in == null) return null;
int n = 0;
int j;
byte[] a = null;
- while ((j = in.available()) > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- n += in.read(a, n, j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ j = in.available();
}
- return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
+ while (j > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ n += in.read(a, n, j);
+ j = in.available();
+ }
+ }
+ return (a == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
}
/** Called by the process reaper thread when the process exits. */
synchronized void processExited() {
- // Most BufferedInputStream methods are synchronized, but close()
- // is not, and so we have to handle concurrent racing close().
try {
InputStream in = this.in;
if (in != null) {
- byte[] stragglers = drainInputStream(in);
+ InputStream stragglers = drainInputStream(in);
in.close();
- this.in = (stragglers == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(stragglers);
- if (buf == null) // asynchronous close()?
- this.in = null;
+ this.in = stragglers;
}
- } catch (IOException ignored) {
- // probably an asynchronous close().
+ } catch (IOException ignored) { }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other methods.
+ // Synchronizing helps avoid racing with drainInputStream().
+ synchronized (closeLock) {
+ super.close();
}
}
}
diff --git a/src/solaris/classes/java/lang/UNIXProcess.java.linux b/src/solaris/classes/java/lang/UNIXProcess.java.linux
index 52fef02..5ce8a61 100644
--- a/src/solaris/classes/java/lang/UNIXProcess.java.linux
+++ b/src/solaris/classes/java/lang/UNIXProcess.java.linux
@@ -339,40 +339,54 @@
* able to read any buffered data lingering in the OS pipe buffer.
*/
static class ProcessPipeInputStream extends BufferedInputStream {
+ private final Object closeLock = new Object();
+
ProcessPipeInputStream(int fd) {
super(new FileInputStream(newFileDescriptor(fd)));
}
- private static byte[] drainInputStream(InputStream in)
+ private InputStream drainInputStream(InputStream in)
throws IOException {
- if (in == null) return null;
int n = 0;
int j;
byte[] a = null;
- while ((j = in.available()) > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- n += in.read(a, n, j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ j = in.available();
}
- return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
+ while (j > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ n += in.read(a, n, j);
+ j = in.available();
+ }
+ }
+ return (a == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
}
/** Called by the process reaper thread when the process exits. */
synchronized void processExited() {
- // Most BufferedInputStream methods are synchronized, but close()
- // is not, and so we have to handle concurrent racing close().
try {
InputStream in = this.in;
if (in != null) {
- byte[] stragglers = drainInputStream(in);
+ InputStream stragglers = drainInputStream(in);
in.close();
- this.in = (stragglers == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(stragglers);
- if (buf == null) // asynchronous close()?
- this.in = null;
+ this.in = stragglers;
}
- } catch (IOException ignored) {
- // probably an asynchronous close().
+ } catch (IOException ignored) { }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other methods.
+ // Synchronizing helps avoid racing with drainInputStream().
+ synchronized (closeLock) {
+ super.close();
}
}
}
diff --git a/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java b/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java
index af3a474..907f884 100644
--- a/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java
+++ b/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java
@@ -70,12 +70,12 @@
// GIO may access file so need permission check
path.checkRead();
byte[] type = probeUsingGio(buffer.address());
- return (type == null) ? null : new String(type);
+ return (type == null) ? null : Util.toString(type);
} else {
byte[] type = probeUsingGnomeVfs(buffer.address());
if (type == null)
return null;
- String s = new String(type);
+ String s = Util.toString(type);
return s.equals(GNOME_VFS_MIME_TYPE_UNKNOWN) ? null : s;
}
} finally {
diff --git a/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
index 4a97e09..0a3f32e 100644
--- a/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
+++ b/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
@@ -51,7 +51,7 @@
private static final String HIDDEN_NAME = "hidden";
private static final String DOS_XATTR_NAME = "user.DOSATTRIB";
- private static final byte[] DOS_XATTR_NAME_AS_BYTES = DOS_XATTR_NAME.getBytes();
+ private static final byte[] DOS_XATTR_NAME_AS_BYTES = Util.toBytes(DOS_XATTR_NAME);
private static final int DOS_XATTR_READONLY = 0x01;
private static final int DOS_XATTR_HIDDEN = 0x02;
@@ -225,7 +225,7 @@
byte[] buf = new byte[len];
unsafe.copyMemory(null, buffer.address(), buf,
Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
- String value = new String(buf); // platform encoding
+ String value = Util.toString(buf);
// should be something like 0x20
if (value.length() >= 3 && value.startsWith("0x")) {
@@ -263,7 +263,7 @@
newValue &= ~flag;
}
if (newValue != oldValue) {
- byte[] value = ("0x" + Integer.toHexString(newValue)).getBytes();
+ byte[] value = Util.toBytes("0x" + Integer.toHexString(newValue));
NativeBuffer buffer = NativeBuffers.asNativeBuffer(value);
try {
LinuxNativeDispatcher.fsetxattr(fd, DOS_XATTR_NAME_AS_BYTES,
diff --git a/src/solaris/classes/sun/nio/fs/LinuxFileStore.java b/src/solaris/classes/sun/nio/fs/LinuxFileStore.java
index 3f0bcb9..6073613 100644
--- a/src/solaris/classes/sun/nio/fs/LinuxFileStore.java
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileStore.java
@@ -98,7 +98,8 @@
int fd = path.openForAttributeAccess(false);
try {
// fgetxattr returns size if called with size==0
- LinuxNativeDispatcher.fgetxattr(fd, "user.java".getBytes(), 0L, 0);
+ byte[] name = Util.toBytes("user.java");
+ LinuxNativeDispatcher.fgetxattr(fd, name, 0L, 0);
return true;
} catch (UnixException e) {
// attribute does not exist
diff --git a/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java b/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
index eff7b58..54d8347 100644
--- a/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
+++ b/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
@@ -78,7 +78,7 @@
Iterable<UnixMountEntry> getMountEntries(String fstab) {
ArrayList<UnixMountEntry> entries = new ArrayList<>();
try {
- long fp = setmntent(fstab.getBytes(), "r".getBytes());
+ long fp = setmntent(Util.toBytes(fstab), Util.toBytes("r"));
try {
for (;;) {
UnixMountEntry entry = new UnixMountEntry();
diff --git a/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java b/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java
index 46e7f2c..fec8d5e 100644
--- a/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java
+++ b/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java
@@ -53,7 +53,7 @@
if (name == null)
throw new NullPointerException("'name' is null");
name = USER_NAMESPACE + name;
- byte[] bytes = name.getBytes();
+ byte[] bytes = Util.toBytes(name);
if (bytes.length > XATTR_NAME_MAX) {
throw new FileSystemException(file.getPathForExceptionMessage(),
null, "'" + name + "' is too big");
@@ -72,7 +72,7 @@
byte[] value = new byte[len];
unsafe.copyMemory(null, address+start, value,
Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
- String s = new String(value);
+ String s = Util.toString(value);
if (s.startsWith(USER_NAMESPACE)) {
s = s.substring(USER_NAMESPACE.length());
list.add(s);
diff --git a/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java b/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
index 2412e04..d3a34ca 100644
--- a/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
+++ b/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java
@@ -42,9 +42,11 @@
class SolarisUserDefinedFileAttributeView
extends AbstractUserDefinedFileAttributeView
{
+ private static final byte[] HERE = { '.' };
+
private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
- byte[] bytes = name.getBytes();
- // "", "." and ".." not allowed
+ byte[] bytes = Util.toBytes(name);
+ // "", "." and ".." not allowed
if (bytes.length == 0 || bytes[0] == '.') {
if (bytes.length <= 1 ||
(bytes.length == 2 && bytes[1] == '.'))
@@ -73,7 +75,7 @@
try {
try {
// open extended attribute directory
- int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+ int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0);
long dp;
try {
dp = fdopendir(dfd);
@@ -87,7 +89,7 @@
try {
byte[] name;
while ((name = readdir(dp)) != null) {
- String s = new String(name);
+ String s = Util.toString(name);
if (!s.equals(".") && !s.equals(".."))
list.add(s);
}
@@ -217,7 +219,7 @@
int fd = file.openForAttributeAccess(followLinks);
try {
- int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+ int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0);
try {
unlinkat(dfd, nameAsBytes(file,name), 0);
} finally {
@@ -243,7 +245,7 @@
static void copyExtendedAttributes(int ofd, int nfd) {
try {
// open extended attribute directory
- int dfd = openat(ofd, ".".getBytes(), (O_RDONLY|O_XATTR), 0);
+ int dfd = openat(ofd, HERE, (O_RDONLY|O_XATTR), 0);
long dp = 0L;
try {
dp = fdopendir(dfd);
diff --git a/src/solaris/classes/sun/nio/fs/UnixException.java b/src/solaris/classes/sun/nio/fs/UnixException.java
index b4925c3..80174c7 100644
--- a/src/solaris/classes/sun/nio/fs/UnixException.java
+++ b/src/solaris/classes/sun/nio/fs/UnixException.java
@@ -61,7 +61,7 @@
if (msg != null) {
return msg;
} else {
- return new String(UnixNativeDispatcher.strerror(errno()));
+ return Util.toString(UnixNativeDispatcher.strerror(errno()));
}
}
diff --git a/src/solaris/classes/sun/nio/fs/UnixFileStore.java b/src/solaris/classes/sun/nio/fs/UnixFileStore.java
index 4299b26..38465fb 100644
--- a/src/solaris/classes/sun/nio/fs/UnixFileStore.java
+++ b/src/solaris/classes/sun/nio/fs/UnixFileStore.java
@@ -196,7 +196,7 @@
@Override
public String toString() {
- StringBuilder sb = new StringBuilder(new String(entry.dir()));
+ StringBuilder sb = new StringBuilder(Util.toString(entry.dir()));
sb.append(" (");
sb.append(entry.name());
sb.append(")");
diff --git a/src/solaris/classes/sun/nio/fs/UnixFileSystem.java b/src/solaris/classes/sun/nio/fs/UnixFileSystem.java
index 21aefc1..c7111e9 100644
--- a/src/solaris/classes/sun/nio/fs/UnixFileSystem.java
+++ b/src/solaris/classes/sun/nio/fs/UnixFileSystem.java
@@ -49,7 +49,7 @@
// package-private
UnixFileSystem(UnixFileSystemProvider provider, String dir) {
this.provider = provider;
- this.defaultDirectory = UnixPath.normalizeAndCheck(dir).getBytes();
+ this.defaultDirectory = Util.toBytes(UnixPath.normalizeAndCheck(dir));
if (this.defaultDirectory[0] != '/') {
throw new RuntimeException("default directory must be absolute");
}
@@ -204,7 +204,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
- sm.checkRead(new String(entry.dir()));
+ sm.checkRead(Util.toString(entry.dir()));
} catch (SecurityException x) {
continue;
}
diff --git a/src/solaris/classes/sun/nio/fs/UnixMountEntry.java b/src/solaris/classes/sun/nio/fs/UnixMountEntry.java
index 8a46e45..af23322 100644
--- a/src/solaris/classes/sun/nio/fs/UnixMountEntry.java
+++ b/src/solaris/classes/sun/nio/fs/UnixMountEntry.java
@@ -43,12 +43,12 @@
}
String name() {
- return new String(name);
+ return Util.toString(name);
}
String fstype() {
if (fstypeAsString == null)
- fstypeAsString = new String(fstype);
+ fstypeAsString = Util.toString(fstype);
return fstypeAsString;
}
@@ -65,7 +65,7 @@
*/
boolean hasOption(String requested) {
if (optionsAsString == null)
- optionsAsString = new String(opts);
+ optionsAsString = Util.toString(opts);
for (String opt: Util.split(optionsAsString, ',')) {
if (opt.equals(requested))
return true;
diff --git a/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
index ec21e6d..043a7c0 100644
--- a/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
+++ b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
@@ -100,7 +100,7 @@
*/
static long fopen(UnixPath filename, String mode) throws UnixException {
NativeBuffer pathBuffer = copyToNativeBuffer(filename);
- NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(mode.getBytes());
+ NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(Util.toBytes(mode));
try {
return fopen0(pathBuffer.address(), modeBuffer.address());
} finally {
@@ -473,7 +473,7 @@
* @return passwd->pw_uid
*/
static int getpwnam(String name) throws UnixException {
- NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes());
+ NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
try {
return getpwnam0(buffer.address());
} finally {
@@ -488,7 +488,7 @@
* @return group->gr_name
*/
static int getgrnam(String name) throws UnixException {
- NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes());
+ NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
try {
return getgrnam0(buffer.address());
} finally {
diff --git a/src/solaris/classes/sun/nio/fs/UnixPath.java b/src/solaris/classes/sun/nio/fs/UnixPath.java
index e3462fa..0d358f2 100644
--- a/src/solaris/classes/sun/nio/fs/UnixPath.java
+++ b/src/solaris/classes/sun/nio/fs/UnixPath.java
@@ -120,7 +120,7 @@
SoftReference<CharsetEncoder> ref = encoder.get();
CharsetEncoder ce = (ref != null) ? ref.get() : null;
if (ce == null) {
- ce = Charset.defaultCharset().newEncoder()
+ ce = Util.jnuEncoding().newEncoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
encoder.set(new SoftReference<CharsetEncoder>(ce));
@@ -186,7 +186,7 @@
// use this path for permission checks
String getPathForPermissionCheck() {
if (getFileSystem().needToResolveAgainstDefaultDirectory()) {
- return new String(getByteArrayForSysCalls());
+ return Util.toString(getByteArrayForSysCalls());
} else {
return toString();
}
@@ -758,7 +758,7 @@
public String toString() {
// OK if two or more threads create a String
if (stringValue == null) {
- stringValue = fs.normalizeJavaPath(new String(path)); // platform encoding
+ stringValue = fs.normalizeJavaPath(Util.toString(path)); // platform encoding
}
return stringValue;
}
diff --git a/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java b/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java
index 163dbdd..187bb23 100644
--- a/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java
+++ b/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java
@@ -115,7 +115,7 @@
static User fromUid(int uid) {
String name = null;
try {
- name = new String(getpwuid(uid));
+ name = Util.toString(getpwuid(uid));
} catch (UnixException x) {
name = Integer.toString(uid);
}
@@ -126,7 +126,7 @@
static Group fromGid(int gid) {
String name = null;
try {
- name = new String(getgrgid(gid));
+ name = Util.toString(getgrgid(gid));
} catch (UnixException x) {
name = Integer.toString(gid);
}
diff --git a/src/solaris/native/java/net/NetworkInterface.c b/src/solaris/native/java/net/NetworkInterface.c
index 2596b3f..b2ebd8e 100644
--- a/src/solaris/native/java/net/NetworkInterface.c
+++ b/src/solaris/native/java/net/NetworkInterface.c
@@ -170,31 +170,56 @@
JNIEXPORT void JNICALL
Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
+ CHECK_NULL(ni_class);
ni_class = (*env)->NewGlobalRef(env, ni_class);
+ CHECK_NULL(ni_class);
ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
+ CHECK_NULL(ni_nameID);
ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
+ CHECK_NULL(ni_indexID);
ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
+ CHECK_NULL(ni_addrsID);
ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
+ CHECK_NULL(ni_bindsID);
ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
+ CHECK_NULL(ni_descID);
ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
+ CHECK_NULL(ni_virutalID);
ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
+ CHECK_NULL(ni_childsID);
ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
+ CHECK_NULL(ni_parentID);
ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
+ CHECK_NULL(ni_ctrID);
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ CHECK_NULL(ni_iacls);
ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ CHECK_NULL(ni_iacls);
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL(ni_ia4cls);
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ CHECK_NULL(ni_ia4cls);
ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
+ CHECK_NULL(ni_ia6cls);
ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
+ CHECK_NULL(ni_ia6cls);
ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
+ CHECK_NULL(ni_ibcls);
ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
+ CHECK_NULL(ni_ibcls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ CHECK_NULL(ni_ia4ctrID);
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
+ CHECK_NULL(ni_ia6ctrID);
ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
+ CHECK_NULL(ni_ibctrID);
ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
+ CHECK_NULL(ni_ibaddressID);
ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
+ CHECK_NULL(ni_ib4broadcastID);
ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
+ CHECK_NULL(ni_ib4maskID);
ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", "I");
}
diff --git a/src/solaris/native/sun/net/spi/DefaultProxySelector.c b/src/solaris/native/sun/net/spi/DefaultProxySelector.c
index 6d17e2b..76b2e2d 100644
--- a/src/solaris/native/sun/net/spi/DefaultProxySelector.c
+++ b/src/solaris/native/sun/net/spi/DefaultProxySelector.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -31,6 +31,7 @@
#include "sun_net_spi_DefaultProxySelector.h"
#include <dlfcn.h>
#include <stdio.h>
+#include <stdlib.h>
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
#include <string.h>
#else
@@ -60,6 +61,10 @@
* - /system/proxy/no_proxy_for list
* - /system/proxy/gopher_host string
* - /system/proxy/gopher_port int
+ *
+ * The following keys are not used in the new gnome 3
+ * - /system/http_proxy/use_http_proxy
+ * - /system/http_proxy/use_same_proxy
*/
typedef void* gconf_client_get_default_func();
typedef char* gconf_client_get_string_func(void *, char *, void**);
@@ -74,6 +79,36 @@
gconf_init_func* my_gconf_init_func = NULL;
g_type_init_func* my_g_type_init_func = NULL;
+
+/*
+ * GProxyResolver provides synchronous and asynchronous network
+ * proxy resolution. It is based on GSettings, which is the standard
+ * of Gnome 3, to get system settings.
+ *
+ * In the current implementation, GProxyResolver has a higher priority
+ * than the old GConf. And we only resolve the proxy synchronously. In
+ * the future, we can also do the asynchronous network proxy resolution
+ * if necessary.
+ *
+ */
+typedef struct _GProxyResolver GProxyResolver;
+typedef struct _GSocketConnectable GSocketConnectable;
+typedef struct GError GError;
+typedef GProxyResolver* g_proxy_resolver_get_default_func();
+typedef char** g_proxy_resolver_lookup_func();
+typedef GSocketConnectable* g_network_address_parse_uri_func();
+typedef const char* g_network_address_get_hostname_func();
+typedef unsigned short g_network_address_get_port_func();
+typedef void g_strfreev_func();
+
+static g_proxy_resolver_get_default_func* g_proxy_resolver_get_default = NULL;
+static g_proxy_resolver_lookup_func* g_proxy_resolver_lookup = NULL;
+static g_network_address_parse_uri_func* g_network_address_parse_uri = NULL;
+static g_network_address_get_hostname_func* g_network_address_get_hostname = NULL;
+static g_network_address_get_port_func* g_network_address_get_port = NULL;
+static g_strfreev_func* g_strfreev = NULL;
+
+
static jclass proxy_class;
static jclass isaddr_class;
static jclass ptype_class;
@@ -83,11 +118,363 @@
static jfieldID ptype_httpID;
static jfieldID ptype_socksID;
-static int gconf_ver = 0;
+
static void* gconf_client = NULL;
+static int use_gproxyResolver = 0;
+static int use_gconf = 0;
+
#define CHECK_NULL(X) { if ((X) == NULL) fprintf (stderr,"JNI errror at line %d\n", __LINE__); }
+
+static int initGConf() {
+ /**
+ * Let's try to load GConf-2 library
+ */
+ if (dlopen(JNI_LIB_NAME("gconf-2"), RTLD_GLOBAL | RTLD_LAZY) != NULL ||
+ dlopen(VERSIONED_JNI_LIB_NAME("gconf-2", "4"),
+ RTLD_GLOBAL | RTLD_LAZY) != NULL)
+ {
+ /*
+ * Now let's get pointer to the functions we need.
+ */
+ my_g_type_init_func =
+ (g_type_init_func*)dlsym(RTLD_DEFAULT, "g_type_init");
+ my_get_default_func =
+ (gconf_client_get_default_func*)dlsym(RTLD_DEFAULT,
+ "gconf_client_get_default");
+
+ if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
+ /**
+ * Try to connect to GConf.
+ */
+ (*my_g_type_init_func)();
+ gconf_client = (*my_get_default_func)();
+ if (gconf_client != NULL) {
+ my_get_string_func =
+ (gconf_client_get_string_func*)dlsym(RTLD_DEFAULT,
+ "gconf_client_get_string");
+ my_get_int_func =
+ (gconf_client_get_int_func*)dlsym(RTLD_DEFAULT,
+ "gconf_client_get_int");
+ my_get_bool_func =
+ (gconf_client_get_bool_func*)dlsym(RTLD_DEFAULT,
+ "gconf_client_get_bool");
+ if (my_get_int_func != NULL && my_get_string_func != NULL &&
+ my_get_bool_func != NULL)
+ {
+ /**
+ * We did get all we need. Let's enable the System Proxy Settings.
+ */
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static jobject getProxyByGConf(JNIEnv *env, const char* cproto,
+ const char* chost)
+{
+ char *phost = NULL;
+ char *mode = NULL;
+ int pport = 0;
+ int use_proxy = 0;
+ int use_same_proxy = 0;
+ jobject isa = NULL;
+ jobject proxy = NULL;
+ jobject type_proxy = NULL;
+
+ // We only check manual proxy configurations
+ mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
+ if (mode && !strcasecmp(mode, "manual")) {
+ /*
+ * Even though /system/http_proxy/use_same_proxy is no longer used,
+ * its value is set to false in gnome 3. So it is not harmful to check
+ * it first in case jdk is used with an old gnome.
+ */
+ use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL);
+ if (use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+
+ if (!use_proxy) {
+ /**
+ * HTTP:
+ * /system/http_proxy/use_http_proxy (boolean) - it's no longer used
+ * /system/http_proxy/host (string)
+ * /system/http_proxy/port (integer)
+ */
+ if (strcasecmp(cproto, "http") == 0) {
+ phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+
+ /**
+ * HTTPS:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/secure_host (string)
+ * /system/proxy/secure_port (integer)
+ */
+ if (strcasecmp(cproto, "https") == 0) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+
+ /**
+ * FTP:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/ftp_host (string)
+ * /system/proxy/ftp_port (integer)
+ */
+ if (strcasecmp(cproto, "ftp") == 0) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+
+ /**
+ * GOPHER:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/gopher_host (string)
+ * /system/proxy/gopher_port (integer)
+ */
+ if (strcasecmp(cproto, "gopher") == 0) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+
+ /**
+ * SOCKS:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/socks_host (string)
+ * /system/proxy/socks_port (integer)
+ */
+ if (strcasecmp(cproto, "socks") == 0) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
+ use_proxy = (phost != NULL && pport != 0);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
+ }
+ }
+ }
+
+ if (use_proxy) {
+ jstring jhost;
+ char *noproxyfor;
+ char *s;
+
+ /**
+ * check for the exclude list (aka "No Proxy For" list).
+ * It's a list of comma separated suffixes (e.g. domain name).
+ */
+ noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
+ if (noproxyfor != NULL) {
+ char *tmpbuf[512];
+ s = strtok_r(noproxyfor, ", ", tmpbuf);
+
+ while (s != NULL && strlen(s) <= strlen(chost)) {
+ if (strcasecmp(chost+(strlen(chost) - strlen(s)), s) == 0) {
+ /**
+ * the URL host name matches with one of the sufixes,
+ * therefore we have to use a direct connection.
+ */
+ use_proxy = 0;
+ break;
+ }
+ s = strtok_r(NULL, ", ", tmpbuf);
+ }
+ }
+ if (use_proxy) {
+ CHECK_NULL(type_proxy);
+ jhost = (*env)->NewStringUTF(env, phost);
+ isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
+ proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
+ }
+ }
+
+ return proxy;
+}
+
+static int initGProxyResolver() {
+ void *gio_handle;
+
+ gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
+ if (!gio_handle) {
+ gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
+ if (!gio_handle) {
+ return 0;
+ }
+ }
+
+ my_g_type_init_func = (g_type_init_func*)dlsym(gio_handle, "g_type_init");
+
+ g_proxy_resolver_get_default =
+ (g_proxy_resolver_get_default_func*)dlsym(gio_handle,
+ "g_proxy_resolver_get_default");
+
+ g_proxy_resolver_lookup =
+ (g_proxy_resolver_lookup_func*)dlsym(gio_handle,
+ "g_proxy_resolver_lookup");
+
+ g_network_address_parse_uri =
+ (g_network_address_parse_uri_func*)dlsym(gio_handle,
+ "g_network_address_parse_uri");
+
+ g_network_address_get_hostname =
+ (g_network_address_get_hostname_func*)dlsym(gio_handle,
+ "g_network_address_get_hostname");
+
+ g_network_address_get_port =
+ (g_network_address_get_port_func*)dlsym(gio_handle,
+ "g_network_address_get_port");
+
+ g_strfreev = (g_strfreev_func*)dlsym(gio_handle, "g_strfreev");
+
+ if (!my_g_type_init_func ||
+ !g_proxy_resolver_get_default ||
+ !g_proxy_resolver_lookup ||
+ !g_network_address_parse_uri ||
+ !g_network_address_get_hostname ||
+ !g_network_address_get_port ||
+ !g_strfreev)
+ {
+ dlclose(gio_handle);
+ return 0;
+ }
+
+ (*my_g_type_init_func)();
+ return 1;
+}
+
+static jobject getProxyByGProxyResolver(JNIEnv *env, const char* cproto,
+ const char* chost)
+{
+ GProxyResolver* resolver = NULL;
+ char** proxies = NULL;
+ GError *error = NULL;
+
+ size_t protoLen = 0;
+ size_t hostLen = 0;
+ char* uri = NULL;
+
+ jobject objProxy = NULL;
+
+ resolver = (*g_proxy_resolver_get_default)();
+ if (resolver == NULL) {
+ return NULL;
+ }
+
+ // Construct the uri, cproto + "://" + chost
+ protoLen = strlen(cproto);
+ hostLen = strlen(chost);
+ uri = malloc(protoLen + hostLen + 4);
+ if (!uri) {
+ // Out of memory
+ return NULL;
+ }
+ memcpy(uri, cproto, protoLen);
+ memcpy(uri + protoLen, "://", 3);
+ memcpy(uri + protoLen + 3, chost, hostLen + 1);
+
+ /*
+ * Looks into the system proxy configuration to determine what proxy,
+ * if any, to use to connect to uri. The returned proxy URIs are of
+ * the form <protocol>://[user[:password]@]host:port or direct://,
+ * where <protocol> could be http, rtsp, socks or other proxying protocol.
+ * direct:// is used when no proxy is needed.
+ */
+ proxies = (*g_proxy_resolver_lookup)(resolver, uri, NULL, &error);
+ free(uri);
+
+ if (proxies) {
+ if (!error) {
+ int i;
+ for(i = 0; proxies[i] && !objProxy; i++) {
+ if (strcmp(proxies[i], "direct://")) {
+ GSocketConnectable* conn =
+ (*g_network_address_parse_uri)(proxies[i], 0,
+ &error);
+ if (conn && !error) {
+ const char* phost = NULL;
+ unsigned short pport = 0;
+ phost = (*g_network_address_get_hostname)(conn);
+ pport = (*g_network_address_get_port)(conn);
+ if (phost && pport > 0) {
+ jobject type_proxy = NULL;
+ jstring jhost = NULL;
+ jobject isa = NULL;
+ jfieldID ptype_ID = ptype_httpID;
+ if (!strncmp(proxies[i], "socks", 5)) {
+ ptype_ID = ptype_socksID;
+ }
+
+ type_proxy = (*env)->GetStaticObjectField(env,
+ ptype_class, ptype_ID);
+ CHECK_NULL(type_proxy);
+ jhost = (*env)->NewStringUTF(env, phost);
+ CHECK_NULL(jhost);
+ isa = (*env)->CallStaticObjectMethod(env,
+ isaddr_class, isaddr_createUnresolvedID,
+ jhost, pport);
+ CHECK_NULL(isa);
+ objProxy = (*env)->NewObject(env, proxy_class,
+ proxy_ctrID, type_proxy, isa);
+ }
+ }
+ }
+ }
+ }
+ (*g_strfreev)(proxies);
+ }
+
+ return objProxy;
+}
+
+static void initJavaClass(JNIEnv *env) {
+ jclass cls = NULL;
+ CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy"));
+ proxy_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type"));
+ ptype_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress"));
+ isaddr_class = (*env)->NewGlobalRef(env, cls);
+ proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>",
+ "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
+ CHECK_NULL(proxy_ctrID);
+ pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY",
+ "Ljava/net/Proxy;");
+ CHECK_NULL(pr_no_proxyID);
+ ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP",
+ "Ljava/net/Proxy$Type;");
+ CHECK_NULL(ptype_httpID);
+ ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS",
+ "Ljava/net/Proxy$Type;");
+ CHECK_NULL(ptype_socksID);
+ isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class,
+ "createUnresolved",
+ "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
+ CHECK_NULL(isaddr_createUnresolvedID);
+}
+
+
/*
* Class: sun_net_spi_DefaultProxySelector
* Method: init
@@ -95,57 +482,17 @@
*/
JNIEXPORT jboolean JNICALL
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
- jclass cls = NULL;
- CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy"));
- proxy_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type"));
- ptype_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress"));
- isaddr_class = (*env)->NewGlobalRef(env, cls);
- proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>", "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
- pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;");
- ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;");
- ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;");
- isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved", "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
+ use_gproxyResolver = initGProxyResolver();
+ if (!use_gproxyResolver)
+ use_gconf = initGConf();
- /**
- * Let's try to load le GConf-2 library
- */
- if (dlopen(JNI_LIB_NAME("gconf-2"), RTLD_GLOBAL | RTLD_LAZY) != NULL ||
- dlopen(VERSIONED_JNI_LIB_NAME("gconf-2", "4"),
- RTLD_GLOBAL | RTLD_LAZY) != NULL) {
- gconf_ver = 2;
- }
- if (gconf_ver > 0) {
- /*
- * Now let's get pointer to the functions we need.
- */
- my_g_type_init_func = (g_type_init_func*) dlsym(RTLD_DEFAULT, "g_type_init");
- my_get_default_func = (gconf_client_get_default_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_default");
- if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
- /**
- * Try to connect to GConf.
- */
- (*my_g_type_init_func)();
- gconf_client = (*my_get_default_func)();
- if (gconf_client != NULL) {
- my_get_string_func = (gconf_client_get_string_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_string");
- my_get_int_func = (gconf_client_get_int_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_int");
- my_get_bool_func = (gconf_client_get_bool_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_bool");
- if (my_get_int_func != NULL && my_get_string_func != NULL &&
- my_get_bool_func != NULL) {
- /**
- * We did get all we need. Let's enable the System Proxy Settings.
- */
- return JNI_TRUE;
- }
- }
- }
- }
- return JNI_FALSE;
+ if (use_gproxyResolver || use_gconf) {
+ initJavaClass(env);
+ return JNI_TRUE;
+ } else
+ return JNI_FALSE;
}
-
/*
* Class: sun_net_spi_DefaultProxySelector
* Method: getSystemProxy
@@ -157,179 +504,35 @@
jstring proto,
jstring host)
{
- char *phost = NULL;
- char *mode = NULL;
- int pport = 0;
- int use_proxy = 0;
- int use_same_proxy = 0;
- const char* urlhost;
- jobject isa = NULL;
- jobject proxy = NULL;
- jobject type_proxy = NULL;
- jobject no_proxy = NULL;
- const char *cproto;
- jboolean isCopy;
+ const char* cproto;
+ const char* chost;
- if (gconf_ver > 0) {
- if (gconf_client == NULL) {
- (*my_g_type_init_func)();
- gconf_client = (*my_get_default_func)();
+ jboolean isProtoCopy;
+ jboolean isHostCopy;
+
+ jobject proxy = NULL;
+
+ cproto = (*env)->GetStringUTFChars(env, proto, &isProtoCopy);
+
+ if (cproto != NULL && (use_gproxyResolver || use_gconf)) {
+ chost = (*env)->GetStringUTFChars(env, host, &isHostCopy);
+ if (chost != NULL) {
+ if (use_gproxyResolver)
+ proxy = getProxyByGProxyResolver(env, cproto, chost);
+ else if (use_gconf)
+ proxy = getProxyByGConf(env, cproto, chost);
+
+ if (isHostCopy == JNI_TRUE)
+ (*env)->ReleaseStringUTFChars(env, host, chost);
+ }
+ if (isProtoCopy == JNI_TRUE)
+ (*env)->ReleaseStringUTFChars(env, proto, cproto);
}
- if (gconf_client != NULL) {
- cproto = (*env)->GetStringUTFChars(env, proto, &isCopy);
- if (cproto != NULL) {
- /**
- * We will have to check protocol by protocol as they do use different
- * entries.
- */
- use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL);
- if (use_same_proxy) {
- use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL);
- if (use_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
- }
- }
-
- /**
- * HTTP:
- * /system/http_proxy/use_http_proxy (boolean)
- * /system/http_proxy/host (string)
- * /system/http_proxy/port (integer)
- */
- if (strcasecmp(cproto, "http") == 0) {
- use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL);
- if (use_proxy) {
- if (!use_same_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
- }
- CHECK_NULL(type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID));
- }
- }
-
- /**
- * HTTPS:
- * /system/proxy/mode (string) [ "manual" means use proxy settings ]
- * /system/proxy/secure_host (string)
- * /system/proxy/secure_port (integer)
- */
- if (strcasecmp(cproto, "https") == 0) {
- mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
- if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
- if (!use_same_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL);
- }
- use_proxy = (phost != NULL);
- if (use_proxy)
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
- }
- }
-
- /**
- * FTP:
- * /system/proxy/mode (string) [ "manual" means use proxy settings ]
- * /system/proxy/ftp_host (string)
- * /system/proxy/ftp_port (integer)
- */
- if (strcasecmp(cproto, "ftp") == 0) {
- mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
- if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
- if (!use_same_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
- }
- use_proxy = (phost != NULL);
- if (use_proxy)
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
- }
- }
-
- /**
- * GOPHER:
- * /system/proxy/mode (string) [ "manual" means use proxy settings ]
- * /system/proxy/gopher_host (string)
- * /system/proxy/gopher_port (integer)
- */
- if (strcasecmp(cproto, "gopher") == 0) {
- mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
- if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
- if (!use_same_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL);
- }
- use_proxy = (phost != NULL);
- if (use_proxy)
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
- }
- }
-
- /**
- * SOCKS:
- * /system/proxy/mode (string) [ "manual" means use proxy settings ]
- * /system/proxy/socks_host (string)
- * /system/proxy/socks_port (integer)
- */
- if (strcasecmp(cproto, "socks") == 0) {
- mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
- if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
- if (!use_same_proxy) {
- phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
- pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
- }
- use_proxy = (phost != NULL);
- if (use_proxy)
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
- }
- }
-
- if (isCopy == JNI_TRUE)
- (*env)->ReleaseStringUTFChars(env, proto, cproto);
-
- if (use_proxy && (phost != NULL)) {
- jstring jhost;
- char *noproxyfor;
- char *s;
-
- /**
- * check for the exclude list (aka "No Proxy For" list).
- * It's a list of comma separated suffixes (e.g. domain name).
- */
- noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
- if (noproxyfor != NULL) {
- char *tmpbuf[512];
-
- s = strtok_r(noproxyfor, ", ", tmpbuf);
- urlhost = (*env)->GetStringUTFChars(env, host, &isCopy);
- if (urlhost != NULL) {
- while (s != NULL && strlen(s) <= strlen(urlhost)) {
- if (strcasecmp(urlhost+(strlen(urlhost) - strlen(s)), s) == 0) {
- /**
- * the URL host name matches with one of the sufixes,
- * therefore we have to use a direct connection.
- */
- use_proxy = 0;
- break;
- }
- s = strtok_r(NULL, ", ", tmpbuf);
- }
- if (isCopy == JNI_TRUE)
- (*env)->ReleaseStringUTFChars(env, host, urlhost);
- }
- }
- if (use_proxy) {
- jhost = (*env)->NewStringUTF(env, phost);
- isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
- proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
- return proxy;
- }
- }
- }
+ if (proxy == NULL) {
+ CHECK_NULL(proxy = (*env)->GetStaticObjectField(env, proxy_class,
+ pr_no_proxyID));
}
- }
-
- CHECK_NULL(no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID));
- return no_proxy;
+ return proxy;
}
+
diff --git a/src/windows/native/java/net/Inet6AddressImpl.c b/src/windows/native/java/net/Inet6AddressImpl.c
index 0e6fc30..4531402 100644
--- a/src/windows/native/java/net/Inet6AddressImpl.c
+++ b/src/windows/native/java/net/Inet6AddressImpl.c
@@ -131,18 +131,20 @@
error = getaddrinfo(hostname, NULL, &hints, &res);
- if (WSAGetLastError() == WSATRY_AGAIN) {
- NET_ThrowByNameWithLastError(env,
- JNU_JAVANETPKG "UnknownHostException",
- hostname);
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- return NULL;
- } else if (error) {
- /* report error */
- JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
- (char *)hostname);
- JNU_ReleaseStringPlatformChars(env, host, hostname);
- return NULL;
+ if (error) {
+ if (WSAGetLastError() == WSATRY_AGAIN) {
+ NET_ThrowByNameWithLastError(env,
+ JNU_JAVANETPKG "UnknownHostException",
+ hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ } else {
+ /* report error */
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
} else {
int i = 0;
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
diff --git a/src/windows/native/java/net/NetworkInterface.c b/src/windows/native/java/net/NetworkInterface.c
index ad7bae7..fee8687 100644
--- a/src/windows/native/java/net/NetworkInterface.c
+++ b/src/windows/native/java/net/NetworkInterface.c
@@ -500,32 +500,52 @@
* Get the various JNI ids that we require
*/
ni_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(ni_class);
ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");
+ CHECK_NULL(ni_nameID);
ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
+ CHECK_NULL(ni_displayNameID);
ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
+ CHECK_NULL(ni_indexID);
ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
+ CHECK_NULL(ni_addrsID);
ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
+ CHECK_NULL(ni_bindsID);
ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
+ CHECK_NULL(ni_childsID);
ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
+ CHECK_NULL(ni_ctor);
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ CHECK_NULL(ni_iacls);
ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ CHECK_NULL(ni_iacls);
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL(ni_ia4cls);
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ CHECK_NULL(ni_ia4cls);
ni_ia4Ctor = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ CHECK_NULL(ni_ia4Ctor);
ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
+ CHECK_NULL(ni_ia6cls);
ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
+ CHECK_NULL(ni_ia6cls);
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
+ CHECK_NULL(ni_ia6ctrID);
ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
+ CHECK_NULL(ni_ibcls);
ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
+ CHECK_NULL(ni_ibcls);
ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
+ CHECK_NULL(ni_ibctrID);
ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
+ CHECK_NULL(ni_ibaddressID);
ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
+ CHECK_NULL(ni_ibbroadcastID);
ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
-
}
/*
diff --git a/src/windows/native/sun/nio/ch/SocketDispatcher.c b/src/windows/native/sun/nio/ch/SocketDispatcher.c
index 45fe14b..db45416 100644
--- a/src/windows/native/sun/nio/ch/SocketDispatcher.c
+++ b/src/windows/native/sun/nio/ch/SocketDispatcher.c
@@ -192,45 +192,66 @@
jobject fdo, jlong address, jint len)
{
/* set up */
- int i = 0;
+ int next_index, next_offset, ret=0;
DWORD written = 0;
jint fd = fdval(env, fdo);
struct iovec *iovp = (struct iovec *)address;
WSABUF *bufs = malloc(len * sizeof(WSABUF));
- jint rem = MAX_BUFFER_SIZE;
+ jlong count = 0;
if (bufs == 0) {
JNU_ThrowOutOfMemoryError(env, 0);
return IOS_THROWN;
}
- /* copy iovec into WSABUF */
- for(i=0; i<len; i++) {
- jint iov_len = iovp[i].iov_len;
- if (iov_len > rem)
- iov_len = rem;
- bufs[i].buf = (char *)iovp[i].iov_base;
- bufs[i].len = (u_long)iov_len;
- rem -= iov_len;
- if (rem == 0) {
- len = i+1;
+ // next buffer and offset to consume
+ next_index = 0;
+ next_offset = 0;
+
+ while (next_index < len) {
+ DWORD buf_count = 0;
+
+ /* Prepare the WSABUF array to a maximum total size of MAX_BUFFER_SIZE */
+ jint rem = MAX_BUFFER_SIZE;
+ while (next_index < len && rem > 0) {
+ jint iov_len = iovp[next_index].iov_len - next_offset;
+ char* ptr = (char *)iovp[next_index].iov_base;
+ ptr += next_offset;
+ if (iov_len > rem) {
+ iov_len = rem;
+ next_offset += rem;
+ } else {
+ next_index ++;
+ next_offset = 0;
+ }
+
+ bufs[buf_count].buf = ptr;
+ bufs[buf_count].len = (u_long)iov_len;
+ buf_count++;
+
+ rem -= iov_len;
+ }
+
+ /* write the buffers */
+ ret = WSASend((SOCKET)fd, /* Socket */
+ bufs, /* pointers to the buffers */
+ buf_count, /* number of buffers to process */
+ &written, /* receives number of bytes written */
+ 0, /* no flags */
+ 0, /* no overlapped sockets */
+ 0); /* no completion routine */
+
+ if (ret == SOCKET_ERROR) {
break;
}
- }
- /* read into the buffers */
- i = WSASend((SOCKET)fd, /* Socket */
- bufs, /* pointers to the buffers */
- (DWORD)len, /* number of buffers to process */
- &written, /* receives number of bytes written */
- 0, /* no flags */
- 0, /* no overlapped sockets */
- 0); /* no completion routine */
+ count += written;
+ }
/* clean up */
free(bufs);
- if (i != 0) {
+ if (ret == SOCKET_ERROR && count == 0) {
int theErr = (jint)WSAGetLastError();
if (theErr == WSAEWOULDBLOCK) {
return IOS_UNAVAILABLE;
@@ -239,7 +260,7 @@
return IOS_THROWN;
}
- return convertLongReturnVal(env, (jlong)written, JNI_FALSE);
+ return convertLongReturnVal(env, count, JNI_FALSE);
}
JNIEXPORT void JNICALL
diff --git a/test/ProblemList.txt b/test/ProblemList.txt
index cf4d9b8..ea99549 100644
--- a/test/ProblemList.txt
+++ b/test/ProblemList.txt
@@ -134,10 +134,6 @@
# 8021230
java/lang/ThreadLocal/ThreadLocalSupplierTest.java generic-all
-# 8023201
-java/lang/instrument/RetransformBigClass.sh generic-all
-java/lang/instrument/RedefineBigClass.sh generic-all
-
# 8026502
java/lang/invoke/MethodHandleConstants.java generic-all
@@ -186,9 +182,6 @@
# Filed 7036666
com/sun/net/httpserver/Test9a.java generic-all
-# 7079145 java/net/ipv6tests/UdpTest.java hang at IPv6 only data exchange
-java/net/ipv6tests/UdpTest.java linux-all
-
# 7102670
java/net/InetAddress/CheckJNI.java linux-all
@@ -273,14 +266,8 @@
sun/security/pkcs11/Secmod/AddPrivateKey.java linux-all
sun/security/pkcs11/Secmod/TrustAnchors.java linux-all
-# 7041639, Solaris DSA keypair generation bug (Note: jdk_util also affected)
+# 7041639, Solaris DSA keypair generation bug
java/security/KeyPairGenerator/SolarisShortDSA.java solaris-all
-sun/security/tools/jarsigner/onlymanifest.sh solaris-all
-sun/security/tools/jarsigner/ts.sh solaris-all
-sun/security/tools/keytool/emptysubject.sh solaris-all
-sun/security/tools/keytool/importreadall.sh solaris-all
-sun/security/tools/keytool/readjar.sh solaris-all
-sun/security/tools/keytool/selfissued.sh solaris-all
sun/security/tools/keytool/standard.sh solaris-all
# 8000439: NPG: REGRESSION : sun/security/krb5/auto/MaxRetries.java fails with timeout
@@ -348,7 +335,7 @@
# Filed 6772009
java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all
-# 7041639, Solaris DSA keypair generation bug
-java/util/TimeZone/TimeZoneDatePermissionCheck.sh solaris-all
+# 8026772: test/sun/util/resources/TimeZone/Bug6317929.java failing
+sun/util/resources/TimeZone/Bug6317929.java generic-all
############################################################################
diff --git a/test/TEST.groups b/test/TEST.groups
index c680117..77fae72 100644
--- a/test/TEST.groups
+++ b/test/TEST.groups
@@ -325,7 +325,8 @@
jdk/lambda/separate/Compiler.java \
sun/management/jdp/JdpTest.sh \
sun/management/jmxremote/bootstrap/JvmstatCountersTest.java \
- sun/management/jmxremote/bootstrap/LocalManagementTest.sh \
+ sun/management/jmxremote/bootstrap/LocalManagementTest.java \
+ sun/management/jmxremote/bootstrap/CustomLauncherTest.java \
sun/misc/JarIndex/metaInfFilenames/Basic.java \
sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java \
sun/reflect/CallerSensitive/CallerSensitiveFinder.java \
diff --git a/test/com/sun/corba/5036554/JavaBug.java b/test/com/sun/corba/5036554/JavaBug.java
new file mode 100644
index 0000000..526f6db
--- /dev/null
+++ b/test/com/sun/corba/5036554/JavaBug.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 bug;
+
+public class JavaBug {
+ public static void main(String[] args) {
+ try {
+ org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);
+ org.omg.CORBA.Any any = orb.create_any();
+ myStringHelper.insert(any, "hello");
+ System.out.println("Any: " + myStringHelper.extract(any));
+ } catch( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/com/sun/corba/5036554/README b/test/com/sun/corba/5036554/README
new file mode 100644
index 0000000..cb65e88
--- /dev/null
+++ b/test/com/sun/corba/5036554/README
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+Bug # 5036554 unmarshal error on CORBA alias type in CORBA any
+
+Platform : ALL
+
+Testcase directory : <.../corba>
+
+Test Procedure : <STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
+Step 1: create a file bug.idl with the following content:
+
+// IDL file bug.idl
+module bug {
+ typedef string myString;
+};
+
+Step 2: Translate bug.idl with the command: idlj bug.idl
+This will create the file bug/myStringHelper.java
+
+Step 3:
+Create the file JavaBug.java in directory bug with the following content:
+
+// Java file JavaBug.java
+package bug;
+
+public class JavaBug {
+ public static void main(String[] args) {
+ try {
+ org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);
+ org.omg.CORBA.Any any = orb.create_any();
+ myStringHelper.insert(any, "hello");
+ System.out.println("Any: " + myStringHelper.extract(any));
+ } catch( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+}
+
+Step 4:
+Compile all java files with the command: javac -d . bug\*.java
+
+Step 5:
+Execute the program with the command: java -cp . bug/JavaBug
+
+Step 6: Note the null pointer exception in the the output!
+
+
+Without Fix behaviour : <java.lang.NullPointerException
+ at com.sun.corba.se.internal.corba.TCUtility.unmarshalIn(TCUtility.java:290)
+ at com.sun.corba.se.internal.corba.AnyImpl.read_value(AnyImpl.java:561)
+ at bug.myStringHelper.insert(myStringHelper.java:20)
+ at bug.JavaBug.main(JavaBug.java:8)>
+
+With Fix behaviour : <The output message printed on the console: "Any: hello">
+
+Other Comments : <Test case is automated.>
diff --git a/test/com/sun/corba/5036554/TestCorbaBug.sh b/test/com/sun/corba/5036554/TestCorbaBug.sh
new file mode 100644
index 0000000..983608c
--- /dev/null
+++ b/test/com/sun/corba/5036554/TestCorbaBug.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright (c) 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.
+#
+# 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 5036554 6357706
+# @summary unmarshal error on CORBA alias type in CORBA any
+# @run shell TestCorbaBug.sh
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ echo "TESTJAVA not set, selecting " ${TESTJAVA}
+ echo "If this is incorrect, try setting the variable manually."
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS | Linux | Darwin )
+ PS=":"
+ FS="/"
+ ;;
+ CYGWIN* )
+ PS=";"
+ FS="/"
+ ;;
+ Windows* )
+ PS=";"
+ FS="\\"
+ ;;
+ * )
+ echo "Unrecognized system!"
+ exit 1;
+ ;;
+esac
+
+CLASSPATH=.${PS}${TESTCLASSES}; export CLASSPATH
+
+THIS_DIR=`pwd`
+
+${TESTJAVA}${FS}bin${FS}java -version
+
+mkdir bug
+
+cp ${TESTSRC}${FS}bug.idl .
+${TESTJAVA}${FS}bin${FS}idlj bug.idl
+
+cp ${TESTSRC}${FS}JavaBug.java bug
+
+chmod -fR 777 bug
+
+${TESTJAVA}${FS}bin${FS}javac -d . bug${FS}*.java
+
+${TESTJAVA}${FS}bin${FS}java -cp . bug/JavaBug > test.out 2>&1
+
+grep "NullPointerException" test.out
+
+ERROR=$?
+
+cat test.out
+
+if [ $ERROR = 0 ]
+then
+ echo "Test Failed"
+ exit 1
+fi
+
+grep "Any: hello" test.out
+
+STATUS=$?
+
+if [ $STATUS = 0 ]
+then
+ echo "Test Passed"
+ exit 0
+else
+ echo "Invalid output"
+ cat test.out
+ exit 2
+fi
diff --git a/test/com/sun/corba/5036554/bug.idl b/test/com/sun/corba/5036554/bug.idl
new file mode 100644
index 0000000..af64beb
--- /dev/null
+++ b/test/com/sun/corba/5036554/bug.idl
@@ -0,0 +1,4 @@
+// IDL file bug.idl
+module bug {
+ typedef string myString;
+};
diff --git a/test/com/sun/jdi/GetUninitializedStringValue.java b/test/com/sun/jdi/GetUninitializedStringValue.java
new file mode 100644
index 0000000..7216670
--- /dev/null
+++ b/test/com/sun/jdi/GetUninitializedStringValue.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8021897
+ * @summary Test getting the value for an uninitialized String object
+ *
+ * @author Staffan Larsen
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g GetUninitializedStringValue.java
+ * @run main GetUninitializedStringValue
+ */
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.event.BreakpointEvent;
+
+ /********** target program **********/
+
+class GetUninitializedStringValueTarg {
+ public static void main(String[] args) {
+ new String("foo");
+ System.out.println("Goodbye from GetUninitializedStringValueTarg!");
+ }
+}
+
+ /********** test program **********/
+
+public class GetUninitializedStringValue extends TestScaffold {
+ ReferenceType targetClass;
+ ThreadReference mainThread;
+
+ GetUninitializedStringValue (String args[]) {
+ super(args);
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ new GetUninitializedStringValue (args).startTests();
+ }
+
+ /********** test core **********/
+
+ protected void runTests()
+ throws Exception
+ {
+ /*
+ * Run to String.<init>
+ */
+ startUp("GetUninitializedStringValueTarg");
+ BreakpointEvent bpe = resumeTo("java.lang.String", "<init>", "(Ljava/lang/String;)V");
+
+ /*
+ * We've arrived. Look at 'this' - it will be uninitialized (the value field will not be set yet).
+ */
+ StackFrame frame = bpe.thread().frame(0);
+ StringReference sr = (StringReference)frame.thisObject();
+ if (!sr.value().equals("")) {
+ throw new Exception("Unexpected value for the uninitialized String");
+ }
+
+ /*
+ * resume the target listening for events
+ */
+ listenUntilVMDisconnect();
+ }
+}
diff --git a/test/com/sun/jdi/LambdaBreakpointTest.java b/test/com/sun/jdi/LambdaBreakpointTest.java
new file mode 100644
index 0000000..4800e23
--- /dev/null
+++ b/test/com/sun/jdi/LambdaBreakpointTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/********** LINE NUMBER SENSITIVE! *****************************************************************/
+
+/**
+ * @test
+ * @summary Test setting breakpoints on lambda calls
+ *
+ * @author Staffan Larsen
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g LambdaBreakpointTest.java
+ * @run main LambdaBreakpointTest
+ */
+import java.util.List;
+
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.Location;
+import com.sun.jdi.Method;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.StepEvent;
+
+ /********** target program **********/
+
+class LambdaBreakpointTestTarg {
+
+ static int[] breakpointLines = {
+ 62, 66, 63, 64, 65, 67
+ };
+
+ public static void main(String[] args) {
+ test();
+ }
+
+ private static void test() {
+ Runnable r = () -> { // B1: L62
+ String from = "lambda"; // B3: L63
+ System.out.println("Hello from " + from); // B4: L64
+ }; // B5: L65
+ r.run(); // B2: L66
+ System.out.println("Goodbye."); // B6: L67
+ }
+}
+
+
+ /********** test program **********/
+
+public class LambdaBreakpointTest extends TestScaffold {
+
+ LambdaBreakpointTest (String args[]) {
+ super(args);
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ new LambdaBreakpointTest (args).startTests();
+ }
+
+ /********** test core **********/
+
+ protected void runTests()
+ throws Exception
+ {
+ startToMain("LambdaBreakpointTestTarg");
+
+ // Put a breakpoint on each location in the order they should happen
+ for (int line : LambdaBreakpointTestTarg.breakpointLines) {
+ System.out.println("Running to line: " + line);
+ BreakpointEvent be = resumeTo("LambdaBreakpointTestTarg", line);
+ int stoppedAt = be.location().lineNumber();
+ System.out.println("Stopped at line: " + stoppedAt);
+ if (stoppedAt != line) {
+ throw new Exception("Stopped on the wrong line: "
+ + stoppedAt + " != " + line);
+ }
+ }
+
+ /*
+ * resume the target listening for events
+ */
+ listenUntilVMDisconnect();
+ }
+}
diff --git a/test/com/sun/jdi/LambdaStepTest.java b/test/com/sun/jdi/LambdaStepTest.java
new file mode 100644
index 0000000..c92effa
--- /dev/null
+++ b/test/com/sun/jdi/LambdaStepTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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
+ * @summary Test stepping through lambdas
+ *
+ * @author Staffan Larsen
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g LambdaStepTest.java
+ * @run main LambdaStepTest
+ */
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.StepEvent;
+
+ /********** target program **********/
+
+interface DefaultTest {
+ default void defaultMethod() {
+ String from = "default";
+ System.out.println("Hello from " + from);
+ }
+}
+class LambdaStepTestTarg implements DefaultTest {
+ private void test() {
+ String from = "test";
+ System.out.println("Hello from " + from);
+ }
+ private static void instanceTest() {
+ LambdaStepTestTarg l = new LambdaStepTestTarg();
+ l.test();
+ }
+ private static void lambdaTest() {
+ Runnable r = () -> {
+ String from = "lambda";
+ System.out.println("Hello from " + from);
+ };
+ r.run();
+ }
+ private static void defaultTest() {
+ LambdaStepTestTarg l = new LambdaStepTestTarg();
+ l.defaultMethod();
+ }
+ public static void main(String[] args) {
+ instanceTest();
+ lambdaTest();
+ defaultTest();
+ System.out.println("Goodbye from LambdaStepTestTarg!");
+ }
+}
+
+
+ /********** test program **********/
+
+public class LambdaStepTest extends TestScaffold {
+ LambdaStepTest (String args[]) {
+ super(args);
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ new LambdaStepTest (args).startTests();
+ }
+
+ /********** test core **********/
+
+ protected void runTests()
+ throws Exception
+ {
+ // ## Normal instance method
+
+ BreakpointEvent bpe = startTo("LambdaStepTestTarg", "instanceTest", "()V");
+ ThreadReference thread = bpe.thread();
+
+ // step over allocation
+ StepEvent se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step into test();
+ se = stepIntoLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step over variable initialization
+ se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // get value of variable "from"
+ StackFrame frame = se.thread().frame(0);
+ LocalVariable lv = frame.visibleVariableByName("from");
+ System.out.println(lv);
+ StringReference sr = (StringReference) frame.getValue(lv);
+ if (!sr.value().equals("test")) {
+ throw new Exception("Unexpected variable value in instanceTest: "+sr.value());
+ }
+
+
+ // ## Lambda method
+
+ bpe = resumeTo("LambdaStepTestTarg", "lambdaTest", "()V");
+ thread = bpe.thread();
+
+ // step over allocation
+ se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step into run() of the lambda
+ se = stepIntoLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step over variable initialization
+ se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // get value of variable "from"
+ frame = se.thread().frame(0);
+ lv = frame.visibleVariableByName("from");
+ System.out.println(lv);
+ sr = (StringReference) frame.getValue(lv);
+ if (!sr.value().equals("lambda")) {
+ throw new Exception("Unexpected variable value in lambdaTest: "+sr.value());
+ }
+
+
+ // ## Default method
+
+ bpe = resumeTo("LambdaStepTestTarg", "defaultTest", "()V");
+ thread = bpe.thread();
+
+ // step over allocation
+ se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step into defaultMethod()
+ se = stepIntoLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // step over variable initialization
+ se = stepOverLine(thread);
+ System.out.println(se.thread().frame(0));
+
+ // get value of variable "from"
+ frame = se.thread().frame(0);
+ lv = frame.visibleVariableByName("from");
+ System.out.println(lv);
+ sr = (StringReference) frame.getValue(lv);
+ if (!sr.value().equals("default")) {
+ throw new Exception("Unexpected variable value in lambdaTest: "+sr.value());
+ }
+
+
+ /*
+ * resume the target listening for events
+ */
+ listenUntilVMDisconnect();
+
+ }
+}
diff --git a/test/com/sun/jdi/MethodEntryExitEvents.java b/test/com/sun/jdi/MethodEntryExitEvents.java
index a14a63e..7f9f117 100644
--- a/test/com/sun/jdi/MethodEntryExitEvents.java
+++ b/test/com/sun/jdi/MethodEntryExitEvents.java
@@ -108,14 +108,11 @@
final int expectedExitCount = 1 + (15 * 3);
int methodExitCount = 0;
- /*
- * Class patterns for which we don't want events (copied
- * from the "Trace.java" example):
- * http://java.sun.com/javase/technologies/core/toolsapis/jpda/
- */
- private String[] excludes = {"java.*", "javax.*", "sun.*",
- "com.sun.*", "com.oracle.*",
- "oracle.*", "jdk.internal.*"};
+ // Classes which we are interested in
+ private List includes = Arrays.asList(new String[] {
+ "MethodEntryExitEventsDebugee",
+ "t2"
+ });
MethodEntryExitEvents (String args[]) {
super(args);
@@ -161,6 +158,10 @@
str.disable();
}
public void methodEntered(MethodEntryEvent event) {
+ if (!includes.contains(event.method().declaringType().name())) {
+ return;
+ }
+
if (! finishedCounting) {
// We have to count the entry to loopComplete, but
// not the exit
@@ -176,6 +177,10 @@
}
public void methodExited(MethodExitEvent event) {
+ if (!includes.contains(event.method().declaringType().name())) {
+ return;
+ }
+
if (! finishedCounting){
methodExitCount++;
System.out.print (" Method exit number: ");
@@ -214,6 +219,10 @@
connect((String[]) argList.toArray(args2));
waitForVMStart();
+ // Determine main thread
+ ClassPrepareEvent e = resumeToPrepareOf("MethodEntryExitEventsDebugee");
+ mainThread = e.thread();
+
try {
/*
@@ -223,6 +232,7 @@
eventRequestManager().createExceptionRequest(null, // refType (null == all instances)
true, // notifyCaught
true);// notifyUncaught
+ exceptionRequest.addThreadFilter(mainThread);
exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
exceptionRequest.enable();
@@ -231,9 +241,7 @@
*/
MethodEntryRequest entryRequest =
eventRequestManager().createMethodEntryRequest();
- for (int i=0; i<excludes.length; ++i) {
- entryRequest.addClassExclusionFilter(excludes[i]);
- }
+ entryRequest.addThreadFilter(mainThread);
entryRequest.setSuspendPolicy(sessionSuspendPolicy);
entryRequest.enable();
@@ -242,10 +250,7 @@
*/
MethodExitRequest exitRequest =
eventRequestManager().createMethodExitRequest();
-
- for (int i=0; i<excludes.length; ++i) {
- exitRequest.addClassExclusionFilter(excludes[i]);
- }
+ exitRequest.addThreadFilter(mainThread);
exitRequest.setSuspendPolicy(sessionSuspendPolicy);
exitRequest.enable();
diff --git a/test/com/sun/jdi/MethodExitReturnValuesTest.java b/test/com/sun/jdi/MethodExitReturnValuesTest.java
index af0d937..5658643 100644
--- a/test/com/sun/jdi/MethodExitReturnValuesTest.java
+++ b/test/com/sun/jdi/MethodExitReturnValuesTest.java
@@ -209,18 +209,13 @@
public class MethodExitReturnValuesTest extends TestScaffold {
-
- /*
- * Class patterns for which we don't want events (copied
- * from the "Trace.java" example):
- * http://java.sun.com/javase/technologies/core/toolsapis/jpda/
- */
- private String[] excludes = {
- "javax.*",
- "sun.*",
- "com.sun.*",
- "com.oracle.*",
- "oracle.*"};
+ // Classes which we are interested in
+ private List includes = Arrays.asList(new String[] {
+ "MethodExitReturnValuesTarg",
+ "java.lang.reflect.Array",
+ "java.lang.StrictMath",
+ "java.lang.String"
+ });
static VirtualMachineManager vmm ;
ClassType targetClass;
@@ -487,6 +482,11 @@
// This is the MethodExitEvent handler.
public void methodExited(MethodExitEvent event) {
String origMethodName = event.method().name();
+
+ if (!includes.contains(event.method().declaringType().name())) {
+ return;
+ }
+
if (vmm.majorInterfaceVersion() >= 1 &&
vmm.minorInterfaceVersion() >= 6 &&
vm().canGetMethodReturnValues()) {
@@ -560,10 +560,8 @@
*/
MethodExitRequest exitRequest =
eventRequestManager().createMethodExitRequest();
+ exitRequest.addThreadFilter(mainThread);
- for (int i=0; i<excludes.length; ++i) {
- exitRequest.addClassExclusionFilter(excludes[i]);
- }
int sessionSuspendPolicy = EventRequest.SUSPEND_ALL;
//sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
//sessionSuspendPolicy = EventRequest.SUSPEND_NONE;
diff --git a/test/com/sun/jdi/NullThreadGroupNameTest.java b/test/com/sun/jdi/NullThreadGroupNameTest.java
new file mode 100644
index 0000000..385a989
--- /dev/null
+++ b/test/com/sun/jdi/NullThreadGroupNameTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7105883
+ * @summary Ensure that JDWP doesn't crash with a null thread group name
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run main NullThreadGroupNameTest
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.connect.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import com.sun.jdi.VMDisconnectedException;
+import java.util.concurrent.CountDownLatch;
+import java.util.*;
+
+class DebugTarget {
+ public final static String DEBUG_THREAD_NAME = "DebugThread";
+
+ public static void main(String[] args) throws Exception {
+ DebugThread thread = new DebugThread();
+ thread.start();
+ thread.runningLatch.await();
+ breakpointHere();
+ thread.breakpointLatch.countDown();
+ }
+
+ public static void breakpointHere() {
+ System.out.println("Breakpoint finished!");
+ }
+
+ static class DebugThread extends Thread {
+ final CountDownLatch runningLatch = new CountDownLatch(1);
+ final CountDownLatch breakpointLatch = new CountDownLatch(1);
+
+ public DebugThread() {
+ super(new ThreadGroup(null), DEBUG_THREAD_NAME);
+ }
+
+ public void run() {
+ runningLatch.countDown();
+ try {
+ breakpointLatch.await();
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ }
+ }
+}
+
+public class NullThreadGroupNameTest extends TestScaffold {
+
+ NullThreadGroupNameTest(String args[]) {
+ super(args);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new NullThreadGroupNameTest(args).startTests();
+ }
+
+ protected void runTests() throws Exception {
+ startTo("DebugTarget", "breakpointHere", "()V");
+
+ ThreadReference thread = findThread(DebugTarget.DEBUG_THREAD_NAME);
+ assertThreadGroupName(thread.threadGroup(), "");
+
+ listenUntilVMDisconnect();
+ }
+
+ private ThreadReference findThread(String name) {
+ for (ThreadReference thread : vm().allThreads()) {
+ if (name.equals(thread.name())) {
+ return thread;
+ }
+ }
+ throw new NoSuchElementException("Couldn't find " + name);
+ }
+
+ private void assertThreadGroupName(ThreadGroupReference threadGroup, String expectedName) {
+ try {
+ String name = threadGroup.name();
+ if (!expectedName.equals(name)) {
+ throw new AssertionError("Unexpected thread group name '" + name + "'");
+ }
+ } catch (VMDisconnectedException vmde) {
+ throw new AssertionError("Likely JVM crash with null thread group name", vmde);
+ }
+ }
+}
diff --git a/test/com/sun/jmx/snmp/NoInfoLeakTest.java b/test/com/sun/jmx/snmp/NoInfoLeakTest.java
new file mode 100644
index 0000000..dcf5441
--- /dev/null
+++ b/test/com/sun/jmx/snmp/NoInfoLeakTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8026028
+ * @summary Tests no leak of internal info
+ * @author Shanliang JIANG
+ * @run clean NoInfoLeakTest
+ * @run build NoInfoLeakTest
+ * @run main NoInfoLeakTest
+ */
+
+import com.sun.jmx.snmp.SnmpString;
+import com.sun.jmx.snmp.agent.SnmpMib;
+import com.sun.jmx.snmp.agent.SnmpMibTable;
+import com.sun.jmx.snmp.daemon.CommunicatorServer;
+import com.sun.jmx.snmp.daemon.SnmpAdaptorServer;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+public class NoInfoLeakTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ ok &= snmpStringTest();
+ ok &= snmpMibTest();
+ ok &= communicatorServerTest();
+
+ if (!ok) {
+ throw new RuntimeException("Some tests are failed!");
+ }
+ }
+
+ private static boolean snmpStringTest() {
+ System.out.println("\n---NoInfoLeakTest-snmpStringTest: testing the method byteValue()...");
+ boolean passed = true;
+
+ byte[] mine = new byte[]{1,1,1,};
+ SnmpString ss = new SnmpString(mine);
+ byte[] got = ss.byteValue();
+ got[0]=0;
+
+ if (ss.byteValue()[0] == 0) {
+ System.err.println("Failed: SnmpString.byteValue() returns an internal mutable object value");
+ passed = false;
+ } else {
+ System.out.println("---NoInfoLeakTest-snmpStringTest done.");
+ }
+ return passed;
+ }
+
+ private static boolean snmpMibTest() {
+ boolean passed = true;
+ System.out.println("\n---NoInfoLeakTest-snmpMibTest: testing the method "
+ + "SnmpMib.getRootOid()...");
+ SnmpMib mib = new MySnmpMib();
+
+ if (mib.getRootOid() == mib.getRootOid()) {
+ System.err.println("Failed: SnmpMib.getRootOid() returns an internal"
+ + " mutable object value "+mib.getRootOid());
+ } else {
+ System.out.println("---NoInfoLeakTest-snmpMibTest done.");
+ }
+ return passed;
+ }
+
+ private static boolean communicatorServerTest() {
+ boolean passed = true;
+ System.out.println("\n---NoInfoLeakTest-communicatorServerTest: testing the method CommunicatorServer.getNotificationInfo()...");
+ CommunicatorServer server = new SnmpAdaptorServer();
+ MBeanNotificationInfo[] notifs = server.getNotificationInfo();
+
+ assert notifs.length > 0 && notifs[0] != null; // the current implementation ensures this
+ notifs[0] = null;
+ if (server.getNotificationInfo()[0] == null) {
+ System.err.println("Failed: CommunicatorServer.getNotificationInfo()"
+ + " returns an internal mutable object value");
+ passed = false;
+ } else {
+ System.out.println("---NoInfoLeakTest-communicatorServerTest done.");
+ }
+ return passed;
+ }
+
+ private static class MySnmpMib extends SnmpMib {
+ @Override
+ public void registerTableMeta(String name, SnmpMibTable table) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public SnmpMibTable getRegisteredTableMeta(String name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void init() throws IllegalAccessException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+}
diff --git a/test/java/io/File/NulFile.java b/test/java/io/File/NulFile.java
index 4b83d64..b61b1d8 100644
--- a/test/java/io/File/NulFile.java
+++ b/test/java/io/File/NulFile.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 8003992
+ * @bug 8003992 8027155
* @summary Test a file whose path name is embedded with NUL character, and
* ensure it is handled correctly.
* @author Dan Xu
@@ -613,7 +613,7 @@
File.createTempFile(prefix, suffix, directory);
} catch (IOException ex) {
String err = "Unable to create temporary file";
- if (err.equals(ex.getMessage()))
+ if (ex.getMessage() != null && ex.getMessage().startsWith(err))
exceptionThrown = true;
else {
throw new RuntimeException("Get IOException with message, "
diff --git a/test/java/lang/ProcessBuilder/InheritIOEHandle.java b/test/java/lang/ProcessBuilder/InheritIOEHandle.java
index 87fbf1a..89555c5 100644
--- a/test/java/lang/ProcessBuilder/InheritIOEHandle.java
+++ b/test/java/lang/ProcessBuilder/InheritIOEHandle.java
@@ -35,21 +35,22 @@
public class InheritIOEHandle {
private static enum APP {
- B, C;
+ A, B, C;
}
- private static File stopC = new File(".\\StopC.txt");
+
+ private static File stopC = new File("StopC.txt");
private static String SIGNAL = "After call child process";
private static String JAVA_EXE = System.getProperty("java.home")
- + File.separator + "bin"
- + File.separator + "java";
+ + File.separator + "bin"
+ + File.separator + "java";
private static String[] getCommandArray(String processName) {
String[] cmdArray = {
- JAVA_EXE,
- "-cp",
- System.getProperty("java.class.path"),
- InheritIOEHandle.class.getName(),
- processName
+ JAVA_EXE,
+ "-cp",
+ System.getProperty("java.class.path"),
+ InheritIOEHandle.class.getName(),
+ processName
};
return cmdArray;
}
@@ -59,19 +60,18 @@
return;
}
- if (args.length > 0) {
- APP app = APP.valueOf(args[0]);
- switch (app) {
+ APP app = (args.length > 0) ? APP.valueOf(args[0]) : APP.A;
+ switch (app) {
+ case A:
+ performA();
+ break;
case B:
performB();
break;
case C:
performC();
break;
- }
- return;
}
- performA();
}
private static void performA() {
@@ -87,25 +87,40 @@
process.getOutputStream().close();
process.getErrorStream().close();
- try (BufferedReader in = new BufferedReader( new InputStreamReader(
- process.getInputStream(), "utf-8")))
+ boolean isSignalReceived = false;
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(
+ process.getInputStream(), "utf-8")))
{
String result;
while ((result = in.readLine()) != null) {
- if (!SIGNAL.equals(result)) {
- throw new Error("Catastrophe in process B! Bad output.");
+ if (SIGNAL.equals(result)) {
+ isSignalReceived = true;
+ break;
+ } else {
+ throw new RuntimeException("Catastrophe in process B! Bad output.");
}
}
+
+ }
+ if (!isSignalReceived) {
+ throw new RuntimeException("Signal from B was not received");
}
// If JDK-7147084 is not fixed that point is unreachable.
-
+ System.out.println("Received signal from B, creating file StopC");
// write signal file
- stopC.createNewFile();
+ boolean isFileStopC = stopC.createNewFile();
+ if (!isFileStopC) {
+ throw new RuntimeException("Signal file StopC.txt was not created. TEST or INFRA bug");
+ }
+
+ process.waitFor();
System.err.println("Read stream finished.");
} catch (IOException ex) {
- throw new Error("Catastrophe in process A!", ex);
+ throw new RuntimeException("Catastrophe in process A!", ex);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("A was interrupted while waiting for B", ex);
}
}
@@ -121,27 +136,31 @@
process.getErrorStream().close();
System.out.println(SIGNAL);
+ process.waitFor();
// JDK-7147084 subject:
// Process C inherits the [System.out] handle and
// handle close in B does not finalize the streaming for A.
// (handle reference count > 1).
} catch (IOException ex) {
- throw new Error("Catastrophe in process B!", ex);
+ throw new RuntimeException("Catastrophe in process B!", ex);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("B was interrupted while waiting for C", ex);
}
}
private static void performC() {
// If JDK-7147084 is not fixed the loop is 5min long.
- for (int i = 0; i < 5*60; ++i) {
+ for (int i = 0; i < 5 * 60; ++i) {
try {
Thread.sleep(1000);
- // check for sucess
- if (stopC.exists())
- break;
} catch (InterruptedException ex) {
// that is ok. Longer sleep - better effect.
}
+ // check for success
+ if (stopC.exists()) {
+ break;
+ }
}
}
}
diff --git a/test/java/lang/ProcessBuilder/SiblingIOEHandle.java b/test/java/lang/ProcessBuilder/SiblingIOEHandle.java
index a18e606..2e3cc0b 100644
--- a/test/java/lang/ProcessBuilder/SiblingIOEHandle.java
+++ b/test/java/lang/ProcessBuilder/SiblingIOEHandle.java
@@ -37,21 +37,22 @@
public class SiblingIOEHandle {
private static enum APP {
- B, C;
+ A, B, C;
}
+
private static File stopC = new File(".\\StopCs.txt");
private static String SIGNAL = "B child reported.";
private static String JAVA_EXE = System.getProperty("java.home")
- + File.separator + "bin"
- + File.separator + "java";
+ + File.separator + "bin"
+ + File.separator + "java";
private static String[] getCommandArray(String processName) {
String[] cmdArray = {
- JAVA_EXE,
- "-cp",
- System.getProperty("java.class.path"),
- SiblingIOEHandle.class.getName(),
- processName
+ JAVA_EXE,
+ "-cp",
+ System.getProperty("java.class.path"),
+ SiblingIOEHandle.class.getName(),
+ processName
};
return cmdArray;
}
@@ -61,20 +62,19 @@
return;
}
- if (args.length > 0) {
- APP app = APP.valueOf(args[0]);
- switch (app) {
+ APP app = (args.length > 0) ? APP.valueOf(args[0]) : APP.A;
+ switch (app) {
+ case A:
+ performA(true);
+ performA(false);
+ break;
case B:
performB();
break;
case C:
performC();
break;
- }
- return;
}
- performA(true);
- performA(false);
}
static boolean procClaunched = false;
@@ -86,6 +86,7 @@
// that was long enough
}
}
+
private static boolean waitBarrier(CyclicBarrier barrier) {
while (true) try {
barrier.await();
@@ -98,6 +99,36 @@
}
}
+ private static class ProcessC implements Runnable {
+ private CyclicBarrier barrier;
+ private Process processC;
+
+ public ProcessC(CyclicBarrier barrier) {
+ this.barrier = barrier;
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (waitBarrier(barrier)) {
+ waitAbit();
+ // Run process C next to B ASAP to make an attempt
+ // to capture the B-process IOE handles in C process.
+ ProcessBuilder builderC = new ProcessBuilder(
+ getCommandArray(APP.C.name()));
+ processC = builderC.start();
+ procClaunched = true;
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void waitFor() throws InterruptedException {
+ processC.waitFor();
+ }
+ }
+
private static void performA(boolean fileOut) {
try {
stopC.delete();
@@ -112,26 +143,13 @@
builderB.redirectErrorStream(true);
final CyclicBarrier barrier = new CyclicBarrier(2);
- Thread procCRunner = new Thread(new Runnable() {
- @Override public void run() {
- try {
- if (waitBarrier(barrier)) {
- waitAbit();
- // Run process C next to B ASAP to make an attempt
- // to capture the B-process IOE handles in C process.
- Runtime.getRuntime().exec(getCommandArray(APP.C.name()));
- procClaunched = true;
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- });
+ //Create process C in a new thread
+ ProcessC processC = new ProcessC(barrier);
+ Thread procCRunner = new Thread(processC);
procCRunner.start();
-
if (!waitBarrier(barrier)) {
- throw new Error("Catastrophe in process A! Synchronization failed.");
+ throw new RuntimeException("Catastrophe in process A! Synchronization failed.");
}
// Run process B first.
Process processB = builderB.start();
@@ -144,7 +162,7 @@
}
if (!procClaunched) {
- throw new Error("Catastrophe in process A! C was not launched.");
+ throw new RuntimeException("Catastrophe in process A! C was not launched.");
}
processB.getOutputStream().close();
@@ -154,25 +172,30 @@
try {
processB.waitFor();
} catch (InterruptedException ex) {
- throw new Error("Catastrophe in process B! B hung up.");
+ throw new RuntimeException("Catastrophe in process B! B hung up.");
}
System.err.println("Trying to delete [outB.txt].");
if (!outB.delete()) {
- throw new Error("Greedy brother C deadlock! File share.");
+ throw new RuntimeException("Greedy brother C deadlock! File share.");
}
System.err.println("Succeeded in delete [outB.txt].");
} else {
System.err.println("Read stream start.");
- try (BufferedReader in = new BufferedReader( new InputStreamReader(
- processB.getInputStream(), "utf-8")))
- {
+ boolean isSignalReceived = false;
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(
+ processB.getInputStream(), "utf-8"))) {
String result;
while ((result = in.readLine()) != null) {
- if (!SIGNAL.equals(result)) {
- throw new Error("Catastrophe in process B! Bad output.");
+ if (SIGNAL.equals(result)) {
+ isSignalReceived = true;
+ } else {
+ throw new RuntimeException("Catastrophe in process B! Bad output.");
}
}
}
+ if (!isSignalReceived) {
+ throw new RuntimeException("Signal from B was not received");
+ }
System.err.println("Read stream finished.");
}
// If JDK-6921885 is not fixed that point is unreachable.
@@ -180,8 +203,11 @@
// write signal file to stop C process.
stopC.createNewFile();
+ processC.waitFor();
} catch (IOException ex) {
- throw new Error("Catastrophe in process A!", ex);
+ throw new RuntimeException("Catastrophe in process A!", ex);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("Process A was interrupted while waiting for C", ex);
}
}
@@ -191,7 +217,7 @@
private static void performC() {
// If JDK-7147084 is not fixed the loop is 5min long.
- for (int i = 0; i < 5*60; ++i) {
+ for (int i = 0; i < 5 * 60; ++i) {
try {
Thread.sleep(1000);
// check for sucess
diff --git a/test/java/lang/Runtime/exec/CloseRace.java b/test/java/lang/Runtime/exec/CloseRace.java
new file mode 100644
index 0000000..a1e5790
--- /dev/null
+++ b/test/java/lang/Runtime/exec/CloseRace.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8024521
+ * @summary Closing ProcessPipeInputStream at the time the process exits is racy
+ * and leads to the data corruption.
+ * @library /lib/testlibrary
+ * @run main/othervm/timeout=80 CloseRace
+ */
+
+/**
+ * This test has a little chance to catch the race during the given default
+ * time gap of 20 seconds. To increase the time gap, set the system property
+ * CloseRaceTimeGap=N to the number of seconds.
+ * Jtreg's timeoutFactor should also be set appropriately.
+ *
+ * For example, to run the test for 10 minutes:
+ * > jtreg \
+ * -testjdk:$(PATH_TO_TESTED_JDK) \
+ * -timeoutFactor:10 \
+ * -DCloseRaceTimeGap=600 \
+ * $(PATH_TO_TESTED_JDK_SOURCE)/test/java/lang/Runtime/exec/CloseRace.java
+ */
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.testlibrary.OutputAnalyzer;
+import static jdk.testlibrary.ProcessTools.*;
+
+public class CloseRace {
+
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = createJavaProcessBuilder("-Xmx64M", "CloseRace$Child",
+ System.getProperty("CloseRaceTimeGap", "20"));
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.stderrShouldNotContain("java.lang.OutOfMemoryError");
+ }
+
+ public static class Child {
+ private static final String BIG_FILE = "bigfile";
+ private static final String SMALL_FILE = "smallfile";
+ private static int timeGap = 20; // seconds
+
+ public static void main(String args[]) throws Exception {
+ if (args.length > 0) {
+ try {
+ timeGap = Integer.parseUnsignedInt(args[0]);
+ timeGap = Integer.max(timeGap, 10);
+ timeGap = Integer.min(timeGap, 10 * 60 * 60); // no more than 10 hours
+ } catch (NumberFormatException ignore) {}
+ }
+ try (RandomAccessFile f = new RandomAccessFile(BIG_FILE, "rw")) {
+ f.setLength(1024 * 1024 * 1024); // 1 Gb, greater than max heap size
+ }
+ try (FileOutputStream fs = new FileOutputStream(SMALL_FILE);
+ PrintStream ps = new PrintStream(fs)) {
+ for (int i = 0; i < 128; ++i)
+ ps.println("line of text");
+ }
+
+ List<Thread> threads = new LinkedList<>();
+ for (int i = 0; i < 99; ++i) {
+ Thread t = new Thread (new OpenLoop());
+ t.start();
+ threads.add(t);
+ }
+ Thread t2 = new Thread (new ExecLoop());
+ t2.start();
+ threads.add(t2);
+
+ Thread.sleep(timeGap);
+
+ for (Thread t : threads) {
+ t.interrupt();
+ t.join();
+ }
+ }
+
+ private static class OpenLoop implements Runnable {
+ public void run() {
+ final Path bigFilePath = Paths.get(BIG_FILE);
+ while (!Thread.interrupted()) {
+ try (InputStream in = Files.newInputStream(bigFilePath)) {
+ // Widen the race window by sleeping 1ms
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ break;
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+ }
+ }
+ }
+
+ private static class ExecLoop implements Runnable {
+ public void run() {
+ List<String> command = new ArrayList<>(
+ Arrays.asList("/bin/cat", SMALL_FILE));
+ while (!Thread.interrupted()) {
+ try {
+ ProcessBuilder builder = new ProcessBuilder(command);
+ final Process process = builder.start();
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ while (br.readLine() != null) {}
+ process.waitFor();
+ isr.close();
+ } catch (InterruptedException e) {
+ break;
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/java/lang/SecurityManager/CheckPackageAccess.java b/test/java/lang/SecurityManager/CheckPackageAccess.java
index ba51e9d..ac206c6 100644
--- a/test/java/lang/SecurityManager/CheckPackageAccess.java
+++ b/test/java/lang/SecurityManager/CheckPackageAccess.java
@@ -57,6 +57,7 @@
"com.sun.jmx.",
"com.sun.media.sound.",
"com.sun.proxy.",
+ "com.sun.corba.se.",
"com.sun.org.apache.bcel.internal.",
"com.sun.org.apache.regexp.internal.",
"com.sun.org.apache.xerces.internal.",
diff --git a/test/java/lang/String/ToLowerCase.java b/test/java/lang/String/ToLowerCase.java
index 52fc119..b1edb92 100644
--- a/test/java/lang/String/ToLowerCase.java
+++ b/test/java/lang/String/ToLowerCase.java
@@ -23,7 +23,7 @@
/*
@test
- @bug 4217441 4533872 4900935
+ @bug 4217441 4533872 4900935 8020037
@summary toLowerCase should lower-case Greek Sigma correctly depending
on the context (final/non-final). Also it should handle
Locale specific (lt, tr, and az) lowercasings and supplementary
@@ -69,10 +69,11 @@
test("\u00CD", Locale.US, "\u00ED");
test("\u0128", Locale.US, "\u0129");
- // I-dot tests (Turkish and Azeri)
+ // I-dot tests
test("\u0130", turkish, "i");
test("\u0130", az, "i");
- test("\u0130", Locale.US, "i\u0307");
+ test("\u0130", lt, "i");
+ test("\u0130", Locale.US, "i");
// Remove dot_above in the sequence I + dot_above (Turkish and Azeri)
test("I\u0307", turkish, "i");
diff --git a/test/java/lang/annotation/repeatingAnnotations/InheritedAssociatedAnnotations.java b/test/java/lang/annotation/repeatingAnnotations/InheritedAssociatedAnnotations.java
new file mode 100644
index 0000000..5b190c0
--- /dev/null
+++ b/test/java/lang/annotation/repeatingAnnotations/InheritedAssociatedAnnotations.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8027170
+ * @summary getAnnotationsByType needs to take the class hierarchy into account
+ * when determining which annotations are associated with a given
+ * class.
+ * @run main InheritedAssociatedAnnotations
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.Arrays;
+
+public class InheritedAssociatedAnnotations {
+
+ public static void main(String[] args) {
+ checkAssociated(A3.class);
+ checkAssociated(B3.class);
+ checkAssociated(C3.class);
+ checkAssociated(D3.class);
+ }
+
+ private static void checkAssociated(AnnotatedElement ae) {
+ Ann[] actual = ae.getAnnotationsByType(Ann.class);
+ Ann[] expected = ae.getAnnotation(ExpectedAssociated.class).value();
+
+ if (!Arrays.equals(actual, expected)) {
+ throw new RuntimeException(String.format(
+ "Test failed for %s: Expected %s but got %s.",
+ ae,
+ Arrays.toString(expected),
+ Arrays.toString(actual)));
+ }
+ }
+
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface ExpectedAssociated {
+ Ann[] value();
+}
+
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Repeatable(AnnCont.class)
+@interface Ann {
+ int value();
+}
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@interface AnnCont {
+ Ann[] value();
+}
+
+
+@Ann(10)
+class A1 {}
+
+@Ann(20)
+class A2 extends A1 {}
+
+@ExpectedAssociated({@Ann(20)})
+class A3 extends A2 {}
+
+
+@Ann(10) @Ann(11)
+class B1 {}
+
+@Ann(20)
+class B2 extends B1 {}
+
+@ExpectedAssociated({@Ann(20)})
+class B3 extends B2 {}
+
+
+@Ann(10)
+class C1 {}
+
+@Ann(20) @Ann(21)
+class C2 extends C1 {}
+
+@ExpectedAssociated({@Ann(20), @Ann(21)})
+class C3 extends C2 {}
+
+
+@Ann(10) @Ann(11)
+class D1 {}
+
+@Ann(20) @Ann(21)
+class D2 extends D1 {}
+
+@ExpectedAssociated({@Ann(20), @Ann(21)})
+class D3 extends D2 {}
diff --git a/test/java/lang/annotation/repeatingAnnotations/NonInheritableContainee.java b/test/java/lang/annotation/repeatingAnnotations/NonInheritableContainee.java
new file mode 100644
index 0000000..a4a5ff7
--- /dev/null
+++ b/test/java/lang/annotation/repeatingAnnotations/NonInheritableContainee.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8019420
+ * @summary Repeatable non-inheritable annotation types are mishandled by Core Reflection
+ */
+
+import java.util.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+public class NonInheritableContainee {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Repeatable(InheritedAnnotationContainer.class)
+ @interface NonInheritedAnnotationRepeated {
+ String name();
+ }
+
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface InheritedAnnotationContainer {
+ NonInheritedAnnotationRepeated[] value();
+ }
+
+ @NonInheritedAnnotationRepeated(name="A")
+ @NonInheritedAnnotationRepeated(name="B")
+ class Parent {}
+ class Sample extends Parent {}
+
+
+ public static void main(String[] args) {
+
+ Annotation[] anns = Sample.class.getAnnotationsByType(
+ NonInheritedAnnotationRepeated.class);
+
+ if (anns.length != 0)
+ throw new RuntimeException("Non-@Inherited containees should not " +
+ "be inherited even though its container is @Inherited.");
+ }
+}
diff --git a/test/java/lang/annotation/repeatingAnnotations/OrderUnitTest.java b/test/java/lang/annotation/repeatingAnnotations/OrderUnitTest.java
new file mode 100644
index 0000000..211963f
--- /dev/null
+++ b/test/java/lang/annotation/repeatingAnnotations/OrderUnitTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8004912
+ * @summary Unit test for order of annotations returned by get[Declared]AnnotationsByType.
+ *
+ * @run main OrderUnitTest
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+public class OrderUnitTest {
+
+ public static void main(String[] args) {
+ testOrder(Case1.class);
+ testOrder(Case2.class);
+ }
+
+ private static void testOrder(AnnotatedElement e) {
+ Annotation[] decl = e.getDeclaredAnnotations();
+ Foo[] declByType = e.getDeclaredAnnotationsByType(Foo.class);
+
+ if (decl[0] instanceof Foo != declByType[0].isDirect() ||
+ decl[1] instanceof Foo != declByType[1].isDirect()) {
+ throw new RuntimeException("Order of directly / indirectly present " +
+ "annotations from getDeclaredAnnotationsByType does not " +
+ "match order from getDeclaredAnnotations.");
+ }
+ }
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface FooContainer {
+ Foo[] value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(FooContainer.class)
+@interface Foo {
+ boolean isDirect();
+}
+
+
+@Foo(isDirect = true) @FooContainer({@Foo(isDirect = false)})
+class Case1 {
+}
+
+
+@FooContainer({@Foo(isDirect = false)}) @Foo(isDirect = true)
+class Case2 {
+}
diff --git a/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java
index 674f37f..a1d60ff 100644
--- a/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java
+++ b/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7154390 8005712 8007278
+ * @bug 7154390 8005712 8007278 8004912
* @summary Unit test for repeated annotation reflection
*
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
@@ -51,6 +51,12 @@
inheritedMe3();
inheritedMe4();
+ inheritedMe5(); // ContainerOnSuperSingleOnSub
+ inheritedMe6(); // RepeatableOnSuperSingleOnSub
+ inheritedMe7(); // SingleAnnoOnSuperContainerOnSub
+ inheritedMe8(); // SingleOnSuperRepeatableOnSub
+
+
// CONSTRUCTOR
checkMultiplier(Me1.class.getConstructor(new Class[0]), 10);
@@ -159,6 +165,30 @@
check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 1000);
}
+ static void inheritedMe5() {
+ AnnotatedElement e = Me5.class;
+ check(2 == e.getAnnotations().length);
+ check(1 == countAnnotation(e, InheritedContainee.class));
+ }
+
+ static void inheritedMe6() {
+ AnnotatedElement e = Me6.class;
+ check(2 == e.getAnnotations().length);
+ check(1 == countAnnotation(e, InheritedContainee.class));
+ }
+
+ static void inheritedMe7() {
+ AnnotatedElement e = Me7.class;
+ check(2 == e.getAnnotations().length);
+ check(2 == countAnnotation(e, InheritedContainee.class));
+ }
+
+ static void inheritedMe8() {
+ AnnotatedElement e = Me8.class;
+ check(2 == e.getAnnotations().length);
+ check(2 == countAnnotation(e, InheritedContainee.class));
+ }
+
static void checkMultiplier(AnnotatedElement e, int m) {
// Basic sanity of non-repeating getAnnotation(Class)
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
@@ -252,3 +282,31 @@
@InheritedContainee(1000) @InheritedContainee(2000) @InheritedContainee(3000) @InheritedContainee(4000)
@Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
class Me4 extends Father {}
+
+
+@InheritedContainer({@InheritedContainee(1), @InheritedContainee(2)})
+class SuperOf5 {}
+
+@InheritedContainee(3)
+class Me5 extends SuperOf5{}
+
+
+@InheritedContainee(1) @InheritedContainee(2)
+class SuperOf6 {}
+
+@InheritedContainee(3)
+class Me6 extends SuperOf6 {}
+
+
+@InheritedContainee(1)
+class SuperOf7 {}
+
+@InheritedContainer({@InheritedContainee(2), @InheritedContainee(3)})
+class Me7 extends SuperOf7 {}
+
+
+@InheritedContainee(1)
+class SuperOf8 {}
+
+@InheritedContainee(2) @InheritedContainee(3)
+class Me8 extends SuperOf8 {}
diff --git a/test/java/lang/annotation/typeAnnotations/ConstructorReceiverTest.java b/test/java/lang/annotation/typeAnnotations/ConstructorReceiverTest.java
new file mode 100644
index 0000000..d4a75da
--- /dev/null
+++ b/test/java/lang/annotation/typeAnnotations/ConstructorReceiverTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8023651
+ * @summary Test that the receiver annotations and the return annotations of
+ * constructors behave correctly.
+ * @run testng ConstructorReceiverTest
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.Arrays;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class ConstructorReceiverTest {
+ // Format is {
+ // { Class to get ctor for,
+ // ctor param class,
+ // value of anno of return type,
+ // value of anno for receiver or null if there should be no receiver anno
+ // },
+ // ...
+ // }
+ public static final Object[][] TESTS = {
+ { ConstructorReceiverTest.class, null, Integer.valueOf(5), null },
+ { ConstructorReceiverTest.Middle.class, ConstructorReceiverTest.class, Integer.valueOf(10), Integer.valueOf(15) },
+ { ConstructorReceiverTest.Middle.Inner.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(100), Integer.valueOf(150) },
+ { ConstructorReceiverTest.Middle.Inner.Innermost.class, ConstructorReceiverTest.Middle.Inner.class, Integer.valueOf(1000), Integer.valueOf(1500) },
+ { ConstructorReceiverTest.Middle.InnerNoReceiver.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(300), null },
+ { ConstructorReceiverTest.Nested.class, null, Integer.valueOf(20), null },
+ { ConstructorReceiverTest.Nested.NestedMiddle.class, ConstructorReceiverTest.Nested.class, Integer.valueOf(200), Integer.valueOf(250)},
+ { ConstructorReceiverTest.Nested.NestedMiddle.NestedInner.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(2000), Integer.valueOf(2500)},
+ { ConstructorReceiverTest.Nested.NestedMiddle.NestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(4000), null},
+ };
+
+ @DataProvider
+ public Object[][] data() { return TESTS; }
+
+ @Test(dataProvider = "data")
+ public void testAnnotatedReciver(Class<?> toTest, Class<?> ctorParamType,
+ Integer returnVal, Integer receiverVal) throws NoSuchMethodException {
+ Constructor c;
+ if (ctorParamType == null)
+ c = toTest.getDeclaredConstructor();
+ else
+ c = toTest.getDeclaredConstructor(ctorParamType);
+
+ AnnotatedType annotatedReceiverType = c.getAnnotatedReceiverType();
+ Annotation[] receiverAnnotations = annotatedReceiverType.getAnnotations();
+
+ if (receiverVal == null) {
+ assertEquals(receiverAnnotations.length, 0, Arrays.asList(receiverAnnotations).toString() +
+ " should be empty. Looking at 'length': ");
+ return;
+ }
+
+ assertEquals(receiverAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': ");
+ assertEquals(((Annot)receiverAnnotations[0]).value(), receiverVal.intValue(), " wrong annotation found. Found " +
+ receiverAnnotations[0] +
+ " should find @Annot with value=" +
+ receiverVal);
+ }
+
+ @Test(dataProvider = "data")
+ public void testAnnotatedReturn(Class<?> toTest, Class<?> ctorParamType,
+ Integer returnVal, Integer receiverVal) throws NoSuchMethodException {
+ Constructor c;
+ if (ctorParamType == null)
+ c = toTest.getDeclaredConstructor();
+ else
+ c = toTest.getDeclaredConstructor(ctorParamType);
+
+ AnnotatedType annotatedReturnType = c.getAnnotatedReturnType();
+ Annotation[] returnAnnotations = annotatedReturnType.getAnnotations();
+
+ assertEquals(returnAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': ");
+ assertEquals(((Annot)returnAnnotations[0]).value(), returnVal.intValue(), " wrong annotation found. Found " +
+ returnAnnotations[0] +
+ " should find @Annot with value=" +
+ returnVal);
+ }
+
+ @Annot(5) ConstructorReceiverTest() {}
+
+ private class Middle {
+ @Annot(10) public Middle(@Annot(15) ConstructorReceiverTest ConstructorReceiverTest.this) {}
+
+ public class Inner {
+ @Annot(100) Inner(@Annot(150) Middle Middle.this) {}
+
+ class Innermost {
+ @Annot(1000) private Innermost(@Annot(1500) Inner Inner.this) {}
+ }
+ }
+
+ class InnerNoReceiver {
+ @Annot(300) InnerNoReceiver(Middle Middle.this) {}
+ }
+ }
+
+ public static class Nested {
+ @Annot(20) public Nested() {}
+
+ class NestedMiddle {
+ @Annot(200) public NestedMiddle(@Annot(250) Nested Nested.this) {}
+
+ class NestedInner {
+ @Annot(2000) public NestedInner(@Annot(2500) NestedMiddle NestedMiddle.this) {}
+ }
+
+ class NestedInnerNoReceiver {
+ @Annot(4000) public NestedInnerNoReceiver() {}
+ }
+ }
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE_USE)
+ public static @interface Annot {
+ int value();
+ }
+}
diff --git a/test/java/lang/instrument/NMTHelper.java b/test/java/lang/instrument/NMTHelper.java
new file mode 100644
index 0000000..ad08fdb
--- /dev/null
+++ b/test/java/lang/instrument/NMTHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.DiagnosticCommandMBean;
+
+public class NMTHelper
+{
+ public static void baseline() {
+ executeDcmd("vmNativeMemory", "baseline");
+ }
+
+ // Total: reserved=3484685KB +293KB, committed=266629KB +293KB
+ private static Pattern totalLine = Pattern.compile("^Total: reserved=\\d+KB .*KB, committed=\\d+KB (.*)KB$");
+
+ public static long committedDiff() throws Exception {
+ String res = (String) executeDcmd("vmNativeMemory", "detail.diff");
+ String[] lines = res.split("\n");
+ for (String line : lines) {
+ Matcher matcher = totalLine.matcher(line);
+ if (matcher.matches()) {
+ String committed = matcher.group(1);
+ return Long.parseLong(committed);
+ }
+ }
+ throw new Exception("Could not find the Total line in the NMT output.");
+ }
+
+ private static String executeDcmd(String cmd, String ... args) {
+ DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean();
+ Object[] dcmdArgs = {args};
+ String[] signature = {String[].class.getName()};
+
+ try {
+ System.out.print("> " + cmd + " ");
+ for (String s : args) {
+ System.out.print(s + " ");
+ }
+ System.out.println(":");
+ String result = (String) dcmd.invoke(cmd, dcmdArgs, signature);
+ System.out.println(result);
+ return result;
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/test/java/lang/instrument/RedefineBigClass.sh b/test/java/lang/instrument/RedefineBigClass.sh
index 145be05..82cfd4c 100644
--- a/test/java/lang/instrument/RedefineBigClass.sh
+++ b/test/java/lang/instrument/RedefineBigClass.sh
@@ -58,11 +58,19 @@
JAVAC="${COMPILEJAVA}"/bin/javac
JAVA="${TESTJAVA}"/bin/java
+# Does this VM support the 'detail' level of NMT?
+"${JAVA}" ${TESTVMOPTS} -XX:NativeMemoryTracking=detail -version
+if [ "$?" = 0 ]; then
+ NMT=-XX:NativeMemoryTracking=detail
+else
+ NMT=-XX:NativeMemoryTracking=summary
+fi
+
"${JAVA}" ${TESTVMOPTS} \
- -XX:TraceRedefineClasses=3 \
+ -XX:TraceRedefineClasses=3 ${NMT} \
-javaagent:RedefineBigClassAgent.jar=BigClass.class \
-classpath "${TESTCLASSES}" RedefineBigClassApp \
- > output.log 2>&1
+ > output.log 2>&1
result=$?
cat output.log
diff --git a/test/java/lang/instrument/RedefineBigClassApp.java b/test/java/lang/instrument/RedefineBigClassApp.java
index 8141630..40807d3 100644
--- a/test/java/lang/instrument/RedefineBigClassApp.java
+++ b/test/java/lang/instrument/RedefineBigClassApp.java
@@ -26,16 +26,23 @@
public class RedefineBigClassApp {
/**
* Memory leak is assumed, if application consumes more than specified amount of memory during its execution.
- * The number is given in Kb.
+ * The number is given in KB.
*/
- private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb
+ private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32MB
public static void main(String[] args) throws Exception {
System.out.println("Creating instance of " +
RedefineBigClassAgent.clz);
RedefineBigClassAgent.clz.newInstance();
- long vMemBefore = getVMemSize();
+ // Do a short warmup before creating the NMT baseline
+ try {
+ Thread.sleep(5 * 1000);
+ } catch (InterruptedException ie) {
+ }
+
+ NMTHelper.baseline();
+
int count = 0;
while (!RedefineBigClassAgent.doneRedefining) {
System.out.println("App loop count: " + ++count);
@@ -46,39 +53,12 @@
}
System.out.println("App looped " + count + " times.");
- long vMemAfter = getVMemSize();
- if (vMemBefore == 0 || vMemAfter == 0) {
- System.err.println("WARNING: Cannot perform memory leak detection on this OS");
- } else {
- long vMemDelta = vMemAfter - vMemBefore;
- if (vMemDelta > MEM_LEAK_THRESHOLD) {
- System.err.println("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(greater than " + MEM_LEAK_THRESHOLD + "Kb)");
- System.exit(1);
- }
- System.err.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)");
+ long committedDiff = NMTHelper.committedDiff();
+ if (committedDiff > MEM_LEAK_THRESHOLD) {
+ throw new Exception("FAIL: Committed memory usage increased by " + committedDiff + "KB " +
+ "(greater than " + MEM_LEAK_THRESHOLD + "KB)");
}
- System.exit(0);
- }
-
- /**
- * Return size of virtual memory allocated to the process in Kb.
- * Linux specific. On other platforms and in case of any errors return 0.
- */
- private static long getVMemSize() {
-
- // Refer to the Linux proc(5) man page for details about /proc/self/stat file
- //
- // In short, this file contains status information about the current process
- // written in one line. The fields are separated with spaces.
- // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes'
-
- try (FileReader fileReader = new FileReader("/proc/self/stat");
- BufferedReader bufferedReader = new BufferedReader(fileReader)) {
- String line = bufferedReader.readLine();
- return Long.parseLong(line.split(" ")[22]) / 1024;
- } catch (Exception ex) {}
- return 0;
+ System.err.println("PASS: Committed memory usage increased by " + committedDiff + "KB " +
+ "(not greater than " + MEM_LEAK_THRESHOLD + "KB)");
}
}
diff --git a/test/java/lang/instrument/RedefineMethodInBacktrace.sh b/test/java/lang/instrument/RedefineMethodInBacktrace.sh
index 20167bf..4ebaaa8 100644
--- a/test/java/lang/instrument/RedefineMethodInBacktrace.sh
+++ b/test/java/lang/instrument/RedefineMethodInBacktrace.sh
@@ -62,6 +62,10 @@
RedefineMethodInBacktraceTarget.java
"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTarget.java
+cp "${TESTSRC}"/RedefineMethodInBacktraceTargetB_2.java \
+ RedefineMethodInBacktraceTargetB.java
+"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTargetB.java
+
"${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodInBacktraceAgent.jar \
-classpath "${TESTCLASSES}" RedefineMethodInBacktraceApp > output.log 2>&1
RUN_RESULT=$?
diff --git a/test/java/lang/instrument/RedefineMethodInBacktraceApp.java b/test/java/lang/instrument/RedefineMethodInBacktraceApp.java
index a4ad088..7f7ddbf 100644
--- a/test/java/lang/instrument/RedefineMethodInBacktraceApp.java
+++ b/test/java/lang/instrument/RedefineMethodInBacktraceApp.java
@@ -21,12 +21,17 @@
* questions.
*/
+import com.sun.management.DiagnosticCommandMBean;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.instrument.ClassDefinition;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.concurrent.CountDownLatch;
+import sun.management.ManagementFactoryHelper;
/**
* When an exception is thrown, the JVM collects just enough information
@@ -49,8 +54,12 @@
System.exit(0);
}
+ public static CountDownLatch stop = new CountDownLatch(1);
+ public static CountDownLatch called = new CountDownLatch(1);
+
private void doTest() throws Exception {
doMethodInBacktraceTest();
+ doMethodInBacktraceTestB();
}
private void doMethodInBacktraceTest() throws Exception {
@@ -63,6 +72,36 @@
touchRedefinedMethodInBacktrace(t);
}
+ private void doMethodInBacktraceTestB() throws Exception {
+ // Start a thread which blocks in method
+ Thread t = new Thread(RedefineMethodInBacktraceTargetB::methodToRedefine);
+ t.setDaemon(true);
+ t.start();
+
+ // Wait here until the new thread is in the method we want to redefine
+ called.await();
+
+ // Now redefine the class while the method is still on the stack of the new thread
+ doRedefine(RedefineMethodInBacktraceTargetB.class);
+
+ // Do thread dumps in two different ways (to exercise different code paths)
+ // while the old class is still on the stack
+
+ ThreadInfo[] tis = ManagementFactory.getThreadMXBean().dumpAllThreads(false, false);
+ for(ThreadInfo ti : tis) {
+ System.out.println(ti);
+ }
+
+ String[] threadPrintArgs = {};
+ Object[] dcmdArgs = {threadPrintArgs};
+ String[] signature = {String[].class.getName()};
+ DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean();
+ System.out.println(dcmd.invoke("threadPrint", dcmdArgs, signature));
+
+ // release the thread
+ stop.countDown();
+ }
+
private static Throwable getThrowableFromMethodToRedefine() throws Exception {
Class<RedefineMethodInBacktraceTarget> c =
RedefineMethodInBacktraceTarget.class;
diff --git a/test/java/lang/instrument/RedefineMethodInBacktraceTargetB.java b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB.java
new file mode 100644
index 0000000..baefeb7
--- /dev/null
+++ b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/**
+ * The first version of this class. The second version is in
+ * RedefineMethodInBacktraceTargetB_2.java.
+ */
+public class RedefineMethodInBacktraceTargetB {
+ public static void methodToRedefine() {
+ try {
+ // signal that we are here
+ RedefineMethodInBacktraceApp.called.countDown();
+
+ // wait until test is done
+ RedefineMethodInBacktraceApp.stop.await();
+ } catch (InterruptedException ex) {
+ // ignore, test will fail
+ }
+ }
+}
diff --git a/test/java/lang/instrument/RedefineMethodInBacktraceTargetB_2.java b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB_2.java
new file mode 100644
index 0000000..de98206
--- /dev/null
+++ b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB_2.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This is the second version of this class. The first version is in
+ * RedefineMethodInBacktraceTargetB.java.
+ */
+public class RedefineMethodInBacktraceTargetB {
+ public static void methodToRedefine() {
+ }
+}
diff --git a/test/java/lang/instrument/RetransformBigClass.sh b/test/java/lang/instrument/RetransformBigClass.sh
index dddde89..d168395 100644
--- a/test/java/lang/instrument/RetransformBigClass.sh
+++ b/test/java/lang/instrument/RetransformBigClass.sh
@@ -58,8 +58,16 @@
JAVAC="${COMPILEJAVA}"/bin/javac
JAVA="${TESTJAVA}"/bin/java
+# Does this VM support the 'detail' level of NMT?
+"${JAVA}" ${TESTVMOPTS} -XX:NativeMemoryTracking=detail -version
+if [ "$?" = 0 ]; then
+ NMT=-XX:NativeMemoryTracking=detail
+else
+ NMT=-XX:NativeMemoryTracking=summary
+fi
+
"${JAVA}" ${TESTVMOPTS} \
- -XX:TraceRedefineClasses=3 \
+ -XX:TraceRedefineClasses=3 ${NMT} \
-javaagent:RetransformBigClassAgent.jar=BigClass.class \
-classpath "${TESTCLASSES}" RetransformBigClassApp \
> output.log 2>&1
diff --git a/test/java/lang/instrument/RetransformBigClassApp.java b/test/java/lang/instrument/RetransformBigClassApp.java
index 3f777bb..01e305a 100644
--- a/test/java/lang/instrument/RetransformBigClassApp.java
+++ b/test/java/lang/instrument/RetransformBigClassApp.java
@@ -26,16 +26,23 @@
public class RetransformBigClassApp {
/**
* Memory leak is assumed, if application consumes more than specified amount of memory during its execution.
- * The number is given in Kb.
+ * The number is given in KB.
*/
- private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb
+ private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32MB
public static void main(String[] args) throws Exception {
System.out.println("Creating instance of " +
RetransformBigClassAgent.clz);
RetransformBigClassAgent.clz.newInstance();
- long vMemBefore = getVMemSize();
+ // Do a short warmup before creating the NMT baseline
+ try {
+ Thread.sleep(5 * 1000);
+ } catch (InterruptedException ie) {
+ }
+
+ NMTHelper.baseline();
+
int count = 0;
while (!RetransformBigClassAgent.doneRetransforming) {
System.out.println("App loop count: " + ++count);
@@ -46,39 +53,12 @@
}
System.out.println("App looped " + count + " times.");
- long vMemAfter = getVMemSize();
- if (vMemBefore == 0 || vMemAfter == 0) {
- System.err.println("WARNING: Cannot perform memory leak detection on this OS");
- } else {
- long vMemDelta = vMemAfter - vMemBefore;
- if (vMemDelta > MEM_LEAK_THRESHOLD) {
- System.err.println("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(greater than " + MEM_LEAK_THRESHOLD + "Kb)");
- System.exit(1);
- }
- System.err.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)");
+ long committedDiff = NMTHelper.committedDiff();
+ if (committedDiff > MEM_LEAK_THRESHOLD) {
+ throw new Exception("FAIL: Committed memory usage increased by " + committedDiff + "KB " +
+ "(greater than " + MEM_LEAK_THRESHOLD + "KB)");
}
- System.exit(0);
- }
-
- /**
- * Return size of virtual memory allocated to the process in Kb.
- * Linux specific. On other platforms and in case of any errors return 0.
- */
- private static long getVMemSize() {
-
- // Refer to the Linux proc(5) man page for details about /proc/self/stat file
- //
- // In short, this file contains status information about the current process
- // written in one line. The fields are separated with spaces.
- // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes'
-
- try (FileReader fileReader = new FileReader("/proc/self/stat");
- BufferedReader bufferedReader = new BufferedReader(fileReader)) {
- String line = bufferedReader.readLine();
- return Long.parseLong(line.split(" ")[22]) / 1024;
- } catch (Exception ex) {}
- return 0;
+ System.err.println("PASS: Committed memory usage increased by " + committedDiff + "KB " +
+ "(not greater than " + MEM_LEAK_THRESHOLD + "KB)");
}
}
diff --git a/test/java/lang/invoke/lambda/DupIntf.java b/test/java/lang/invoke/lambda/DupIntf.java
new file mode 100644
index 0000000..e7f366e
--- /dev/null
+++ b/test/java/lang/invoke/lambda/DupIntf.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8025868
+ * @summary Lambda class can be generated with duplicate interfaces (ClassFormatError)
+ * @run main DupIntf
+ */
+
+interface SAM<P1> {
+ P1 m();
+}
+
+interface Other { }
+
+public class DupIntf {
+ public static void main(String argv[]) {
+ SAM<?> sam = (SAM<?> & Other) () -> "Pass.";
+ System.out.println(sam.m());
+ }
+}
diff --git a/test/java/lang/management/ClassLoadingMXBean/LoadCounts.java b/test/java/lang/management/ClassLoadingMXBean/LoadCounts.java
index 33f8f6f..f281bed 100644
--- a/test/java/lang/management/ClassLoadingMXBean/LoadCounts.java
+++ b/test/java/lang/management/ClassLoadingMXBean/LoadCounts.java
@@ -28,10 +28,10 @@
* ClassLoadingMXBean.getTotalLoadedClassCount()
* ClassLoadingMXBean.getUnloadedClassCount()
* @author Alexei Guibadoulline
+ * @run main/othervm LoadCounts
*/
import java.lang.management.*;
-import java.util.*;
public class LoadCounts {
private static ClassLoadingMXBean mbean
@@ -55,13 +55,15 @@
throw new RuntimeException("getLoadedClassCount() > "
+ "getTotalLoadedClassCount()");
- if (classesNowPrev + 4 != classesNow)
+ if (classesNowPrev + 4 > classesNow)
throw new RuntimeException("Number of loaded classes is "
+ + "expected to be at least "
+ (classesNowPrev + 4) + ", but "
+ "MBean.getLoadedClassCount() returned "
+ classesNow);
- if (classesTotalPrev + 4 != classesTotal)
+ if (classesTotalPrev + 4 > classesTotal)
throw new RuntimeException("Total number of loaded classes is "
+ + "expected to be at least "
+ (classesTotalPrev + 4) + ", but "
+ "MBean.getTotalLoadedClassCount() "
+ "returned " + classesTotal);
@@ -95,13 +97,15 @@
// Expected 2 classes got loaded since they are loaded by
// same defining class loader
- if (classesNowPrev + 2 != classesNow)
- throw new RuntimeException("Expected Number of loaded classes is "
+ if (classesNowPrev + 2 > classesNow)
+ throw new RuntimeException("Number of loaded classes is "
+ + "expected to be at least "
+ (classesNowPrev + 4) + ", but "
+ "MBean.getLoadedClassCount() returned "
+ classesNow);
- if (classesTotalPrev + 2 != classesTotal)
+ if (classesTotalPrev + 2 > classesTotal)
throw new RuntimeException("Total number of loaded classes is "
+ + "expected to be at least "
+ (classesTotalPrev + 4) + ", but "
+ "MBean.getTotalLoadedClassCount() "
+ "returned " + classesTotal);
diff --git a/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java b/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java
index b7d88cc..3ae6edb 100644
--- a/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java
+++ b/test/java/lang/management/ManagementFactory/ProxyTypeMapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -36,7 +36,6 @@
import static java.lang.management.ManagementFactory.*;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import com.sun.management.GcInfo;
public class ProxyTypeMapping {
@@ -162,23 +161,23 @@
}
private static void checkMemoryUsage() throws Exception {
- // sanity check to have non-zero usage
+ // sanity check to have non-negative usage
MemoryUsage u1 = memory.getHeapMemoryUsage();
MemoryUsage u2 = memory.getNonHeapMemoryUsage();
MemoryUsage u3 = heapPool.getUsage();
MemoryUsage u4 = nonHeapPool.getUsage();
- if (u1.getCommitted() <= 0 ||
- u2.getCommitted() <= 0 ||
- u3.getCommitted() <= 0 ||
- u4.getCommitted() <= 0) {
+ if (u1.getCommitted() < 0 ||
+ u2.getCommitted() < 0 ||
+ u3.getCommitted() < 0 ||
+ u4.getCommitted() < 0) {
throw new RuntimeException("TEST FAILED: " +
- " expected non-zero committed usage");
+ " expected non-negative committed usage");
}
memory.gc();
MemoryUsage u5 = heapPool.getCollectionUsage();
- if (u5.getCommitted() <= 0) {
+ if (u5.getCommitted() < 0) {
throw new RuntimeException("TEST FAILED: " +
- " expected non-zero committed collected usage");
+ " expected non-negative committed collected usage");
}
}
diff --git a/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java b/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java
index 7797982..cfe8733 100644
--- a/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java
+++ b/test/java/lang/management/ManagementFactory/ValidateOpenTypes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -24,7 +24,7 @@
/*
* @test
* @bug 5024531
- * @summary Validata open types mapped for the MXBeans in the platform
+ * @summary Validate open types mapped for the MXBeans in the platform
* MBeanServer.
* @author Mandy Chung
*
@@ -38,7 +38,6 @@
import static java.lang.management.ManagementFactory.*;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import com.sun.management.GcInfo;
public class ValidateOpenTypes {
@@ -178,23 +177,23 @@
}
private static void checkMemoryUsage() throws Exception {
- // sanity check to have non-zero usage
+ // sanity check to have non-negative usage
Object u1 = server.getAttribute(memory, "HeapMemoryUsage");
Object u2 = server.getAttribute(memory, "NonHeapMemoryUsage");
Object u3 = server.getAttribute(heapPool, "Usage");
Object u4 = server.getAttribute(nonHeapPool, "Usage");
- if (getCommitted(u1) <= 0 ||
- getCommitted(u2) <= 0 ||
- getCommitted(u3) <= 0 ||
- getCommitted(u4) <= 0) {
+ if (getCommitted(u1) < 0 ||
+ getCommitted(u2) < 0 ||
+ getCommitted(u3) < 0 ||
+ getCommitted(u4) < 0) {
throw new RuntimeException("TEST FAILED: " +
- " expected non-zero committed usage");
+ " expected non-negative committed usage");
}
server.invoke(memory, "gc", new Object[0], new String[0]);
Object u5 = server.getAttribute(heapPool, "CollectionUsage");
- if (getCommitted(u5) <= 0) {
+ if (getCommitted(u5) < 0) {
throw new RuntimeException("TEST FAILED: " +
- " expected non-zero committed collected usage");
+ " expected non-negative committed collected usage");
}
}
diff --git a/test/java/lang/management/MemoryPoolMXBean/ThresholdTest.java b/test/java/lang/management/MemoryPoolMXBean/ThresholdTest.java
index 1abb198..62e8473 100644
--- a/test/java/lang/management/MemoryPoolMXBean/ThresholdTest.java
+++ b/test/java/lang/management/MemoryPoolMXBean/ThresholdTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -28,7 +28,7 @@
* MemoryPoolMXBean.isCollectionThresholdExceeded().
* @author Mandy Chung
*
- * @run main ThresholdTest
+ * @run main/othervm ThresholdTest
*/
import java.lang.management.*;
@@ -36,6 +36,9 @@
public class ThresholdTest {
public static void main(String args[]) throws Exception {
+ long[] bigObject = new long[1000000];
+
+ System.gc(); // force an initial full-gc
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
try {
for (MemoryPoolMXBean p : pools) {
@@ -82,6 +85,10 @@
}
p.setUsageThreshold(1);
+ // force a full gc to minimize the likelihood of running GC
+ // between getting the usage and checking the threshold
+ System.gc();
+
MemoryUsage u = p.getUsage();
if (u.getUsed() >= 1) {
if (!p.isUsageThresholdExceeded()) {
diff --git a/test/java/lang/management/ThreadMXBean/ThreadBlockedCount.java b/test/java/lang/management/ThreadMXBean/ThreadBlockedCount.java
index 047a1d6..1cd9032 100644
--- a/test/java/lang/management/ThreadMXBean/ThreadBlockedCount.java
+++ b/test/java/lang/management/ThreadMXBean/ThreadBlockedCount.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -32,7 +32,6 @@
*/
import java.lang.management.*;
-import java.util.concurrent.locks.LockSupport;
public class ThreadBlockedCount {
final static long EXPECTED_BLOCKED_COUNT = 3;
@@ -101,6 +100,7 @@
System.err.println("Unexpected exception.");
e.printStackTrace(System.err);
testFailed = true;
+ break;
}
}
@@ -127,6 +127,7 @@
System.err.println("Unexpected exception.");
e.printStackTrace(System.err);
testFailed = true;
+ break;
}
}
@@ -153,6 +154,7 @@
System.err.println("Unexpected exception.");
e.printStackTrace(System.err);
testFailed = true;
+ break;
}
}
@@ -166,15 +168,25 @@
}
}
- // Check the mbean now
- ThreadInfo ti = mbean.getThreadInfo(Thread.currentThread().
- getId());
- long count = ti.getBlockedCount();
-
+ // wait for the thread stats to be updated for 10 seconds
+ for (int i = 0; i < 100; i++) {
+ if (getBlockedCount() == EXPECTED_BLOCKED_COUNT) {
+ return;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ System.err.println("Unexpected exception.");
+ e.printStackTrace(System.err);
+ testFailed = true;
+ return;
+ }
+ }
+ long count = getBlockedCount();
if (count != EXPECTED_BLOCKED_COUNT) {
System.err.println("TEST FAILED: Blocked thread has " + count +
- " blocked counts. Expected " +
- EXPECTED_BLOCKED_COUNT);
+ " blocked counts. Expected " +
+ EXPECTED_BLOCKED_COUNT);
testFailed = true;
}
} // run()
@@ -195,6 +207,7 @@
System.err.println("Unexpected exception.");
e.printStackTrace(System.err);
testFailed = true;
+ break;
}
ThreadInfo info = mbean.getThreadInfo(blocked.getId());
threadBlocked = (info.getThreadState() == Thread.State.BLOCKED);
@@ -233,4 +246,13 @@
} // run()
} // BlockedThread
+
+ private static long getBlockedCount() {
+ long count;
+ // Check the mbean now
+ ThreadInfo ti = mbean.getThreadInfo(Thread.currentThread().
+ getId());
+ count = ti.getBlockedCount();
+ return count;
+ }
}
diff --git a/test/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java b/test/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java
new file mode 100644
index 0000000..97e9a79
--- /dev/null
+++ b/test/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8005294
+ * @summary Check behavior of default methods of AnnotatedElement
+ * @author Joseph D. Darcy
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * For annotation type tokens including, null, DirectlyPresent.class,
+ * IndirectlyPresent.class, etc. the behavior of
+ * AnnotedElementDelegate.foo(arg) is compared for equality to
+ * baseAnnotatedElement.foo(arg) on various kinds of annotated
+ * elements.
+ */
+public class TestAnnotatedElementDefaults {
+ public static void main(String... args) throws SecurityException {
+ int failures = 0;
+
+ for (AnnotatedElement annotElement : elementsToTest()) {
+ System.out.println(annotElement);
+ AnnotatedElementDelegate delegate = new AnnotatedElementDelegate(annotElement);
+ failures += testNullHandling(delegate);
+ for (Class<? extends Annotation> annotType : annotationsToTest()) {
+ failures += AnnotatedElementDelegate.testDelegate(delegate, annotType);
+ }
+ }
+
+ if (failures > 0) {
+ System.err.printf("%d failures%n", failures);
+ throw new RuntimeException();
+ }
+ }
+
+ private static List<AnnotatedElement> elementsToTest() {
+ List<AnnotatedElement> annotatedElements = new ArrayList<>();
+ annotatedElements.add(TestClass1Super.class);
+ annotatedElements.add(TestClass1.class);
+ for (Method method : TestClass1.class.getDeclaredMethods()) {
+ annotatedElements.add(method);
+ }
+ return annotatedElements;
+ }
+
+ private static List<Class<? extends Annotation>> annotationsToTest() {
+ List<Class<? extends Annotation>> annotations = new ArrayList<>();
+ annotations.add(Missing.class);
+
+ annotations.add(MissingRepeatable.class);
+
+ annotations.add(DirectlyPresent.class);
+
+ annotations.add(IndirectlyPresent.class);
+ annotations.add(IndirectlyPresentContainer.class);
+
+ annotations.add(DirectlyAndIndirectlyPresent.class);
+ annotations.add(DirectlyAndIndirectlyPresentContainer.class);
+
+ annotations.add(AssociatedDirectOnSuperClass.class);
+ annotations.add(AssociatedDirectOnSuperClassContainer.class);
+
+ annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclass.class);
+ annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class);
+
+ annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclass.class);
+ annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class);
+ return annotations;
+ }
+
+ private static int testNullHandling(AnnotatedElementDelegate delegate) {
+ int failures = 0;
+ try {
+ Object result = delegate.getDeclaredAnnotationsByType(null);
+ failures++;
+ } catch (NullPointerException npe) {
+ ; // Expected
+ }
+
+ try {
+ Object result = delegate.getAnnotationsByType(null);
+ failures++;
+ } catch (NullPointerException npe) {
+ ; // Expected
+ }
+
+ try {
+ Object result = delegate.getDeclaredAnnotation(null);
+ failures++;
+ } catch (NullPointerException npe) {
+ ; // Expected
+ }
+
+ return failures;
+ }
+
+}
+
+// -----------------------------------------------------
+
+@AssociatedDirectOnSuperClass(123)
+@AssociatedIndirectOnSuperClass(234) @AssociatedIndirectOnSuperClass(345)
+@AssociatedDirectOnSuperClassIndirectOnSubclass(987)
+@AssociatedIndirectOnSuperClassDirectOnSubclass(1111) @AssociatedIndirectOnSuperClassDirectOnSubclass(2222)
+class TestClass1Super {}
+
+@DirectlyPresent(1)
+@IndirectlyPresent(10) @IndirectlyPresent(11)
+@AssociatedDirectOnSuperClassIndirectOnSubclass(876) @AssociatedDirectOnSuperClassIndirectOnSubclass(765)
+@AssociatedIndirectOnSuperClassDirectOnSubclass(3333)
+class TestClass1 extends TestClass1Super {
+
+ @DirectlyPresent(2)
+ @IndirectlyPresentContainer({@IndirectlyPresent(12)})
+ @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(84), @DirectlyAndIndirectlyPresent(96)})
+ public void foo() {return ;}
+
+ @IndirectlyPresentContainer({})
+ @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(11), @DirectlyAndIndirectlyPresent(22)})
+ @DirectlyAndIndirectlyPresent(33)
+ public void bar() {return ;}
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Missing {
+ int value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(MissingRepeatableContainer.class)
+@interface MissingRepeatable {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface MissingRepeatableContainer {
+ MissingRepeatable[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface DirectlyPresent {
+ int value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(IndirectlyPresentContainer.class)
+@interface IndirectlyPresent {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface IndirectlyPresentContainer {
+ IndirectlyPresent[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(DirectlyAndIndirectlyPresentContainer.class)
+@interface DirectlyAndIndirectlyPresent {
+ int value();
+
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface DirectlyAndIndirectlyPresentContainer {
+ DirectlyAndIndirectlyPresent[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(AssociatedDirectOnSuperClassContainer.class)
+@interface AssociatedDirectOnSuperClass {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AssociatedDirectOnSuperClassContainer {
+ AssociatedDirectOnSuperClass[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(AssociatedIndirectOnSuperClassContainer.class)
+@interface AssociatedIndirectOnSuperClass {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AssociatedIndirectOnSuperClassContainer {
+ AssociatedIndirectOnSuperClass[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class)
+@interface AssociatedDirectOnSuperClassIndirectOnSubclass {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AssociatedDirectOnSuperClassIndirectOnSubclassContainer {
+ AssociatedDirectOnSuperClassIndirectOnSubclass[] value();
+}
+
+// -----------------------------------------------------
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class)
+@interface AssociatedIndirectOnSuperClassDirectOnSubclass {
+ int value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AssociatedIndirectOnSuperClassDirectOnSubclassContainer {
+ AssociatedIndirectOnSuperClassDirectOnSubclass[] value();
+}
+
+// -----------------------------------------------------
+
+/**
+ * Helper class to ease calling the default methods of {@code
+ * AnnotatedElement} and comparing the results to other
+ * implementation.
+ */
+class AnnotatedElementDelegate implements AnnotatedElement {
+ private AnnotatedElement base;
+
+ public AnnotatedElementDelegate(AnnotatedElement base) {
+ Objects.requireNonNull(base);
+ this.base = base;
+ }
+
+ // Delegate to base implemenetation of AnnotatedElement methods
+ // without defaults.
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return base.getAnnotation(annotationClass);
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return base.getAnnotations();
+ }
+
+ @Override
+ public Annotation[] getDeclaredAnnotations() {
+ return base.getDeclaredAnnotations();
+ }
+
+ public AnnotatedElement getBase() {
+ return base;
+ }
+
+ static int testDelegate(AnnotatedElementDelegate delegate,
+ Class<? extends Annotation> annotationClass) {
+ int failures = 0;
+ AnnotatedElement base = delegate.getBase();
+
+ // System.out.println("\tTesting " + delegate + "\ton\t" + annotationClass);
+
+ // <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
+ failures += annotationArrayCheck(delegate.getDeclaredAnnotationsByType(annotationClass),
+ base.getDeclaredAnnotationsByType(annotationClass),
+ annotationClass,
+ "Equality failure on getDeclaredAnnotationsByType(%s) on %s)%n");
+
+ // <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
+ failures += annotationArrayCheck(delegate.getAnnotationsByType(annotationClass),
+ base.getAnnotationsByType(annotationClass),
+ annotationClass,
+ "Equality failure on getAnnotationsByType(%s) on %s)%n");
+
+ // <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
+ if (!Objects.equals(delegate.getDeclaredAnnotation(annotationClass),
+ base.getDeclaredAnnotation(annotationClass))) {
+ failures++;
+ System.err.printf("Equality failure on getDeclaredAnnotation(%s) on %s)%n",
+ annotationClass, delegate);
+ }
+ return failures;
+ }
+ private static <T extends Annotation> int annotationArrayCheck(T[] delegate,
+ T[] base,
+ Class<? extends Annotation> annotationClass,
+ String message) {
+ int failures = 0;
+
+ if (!Objects.deepEquals(delegate,base)) {
+ failures = 1;
+
+ System.err.printf(message,
+ annotationClass,
+ delegate);
+
+ System.err.println("Base result:\t" + Arrays.toString(base));
+ System.err.println("Delegate result:\t " + Arrays.toString(delegate));
+ System.err.println();
+ }
+
+ return failures;
+ }
+}
diff --git a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java
index 28d49be..215ee3d 100644
--- a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java
+++ b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java
@@ -44,30 +44,86 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
import org.testng.annotations.Test;
import static helper.Mod.*;
import static helper.Declared.*;
import helper.Mod;
+
public class DefaultStaticInvokeTest {
+ // getMethods(): Make sure getMethods returns the expected methods.
@Test(dataProvider = "testCasesAll",
dataProviderClass = DefaultStaticTestData.class)
public void testGetMethods(String testTarget, Object param)
throws Exception {
- // test the methods retrieved by getMethods()
testMethods(ALL_METHODS, testTarget, param);
}
+
+ // getDeclaredMethods(): Make sure getDeclaredMethods returns the expected methods.
@Test(dataProvider = "testCasesAll",
dataProviderClass = DefaultStaticTestData.class)
public void testGetDeclaredMethods(String testTarget, Object param)
throws Exception {
- // test the methods retrieved by getDeclaredMethods()
testMethods(DECLARED_ONLY, testTarget, param);
}
+
+ // getMethod(): Make sure that getMethod finds all methods it should find.
+ @Test(dataProvider = "testCasesAll",
+ dataProviderClass = DefaultStaticTestData.class)
+ public void testGetMethod(String testTarget, Object param)
+ throws Exception {
+
+ Class<?> typeUnderTest = Class.forName(testTarget);
+
+ MethodDesc[] descs = typeUnderTest.getAnnotationsByType(MethodDesc.class);
+
+ for (MethodDesc desc : descs) {
+ assertTrue(isFoundByGetMethod(typeUnderTest,
+ desc.name(),
+ argTypes(param)));
+ }
+ }
+
+
+ // getMethod(): Make sure that getMethod does *not* find certain methods.
+ @Test(dataProvider = "testCasesAll",
+ dataProviderClass = DefaultStaticTestData.class)
+ public void testGetMethodSuperInterfaces(String testTarget, Object param)
+ throws Exception {
+
+ // Make sure static methods in superinterfaces are not found (unless the type under
+ // test declares a static method with the same signature).
+
+ Class<?> typeUnderTest = Class.forName(testTarget);
+
+ for (Class<?> interfaze : typeUnderTest.getInterfaces()) {
+
+ for (MethodDesc desc : interfaze.getAnnotationsByType(MethodDesc.class)) {
+
+ boolean isStatic = desc.mod() == STATIC;
+
+ boolean declaredInThisType = isMethodDeclared(typeUnderTest,
+ desc.name());
+
+ boolean expectedToBeFound = !isStatic || declaredInThisType;
+
+ if (expectedToBeFound)
+ continue; // already tested in testGetMethod()
+
+ assertFalse(isFoundByGetMethod(typeUnderTest,
+ desc.name(),
+ argTypes(param)));
+ }
+ }
+ }
+
+
+ // Method.invoke(): Make sure Method.invoke returns the expected value.
@Test(dataProvider = "testCasesAll",
dataProviderClass = DefaultStaticTestData.class)
public void testMethodInvoke(String testTarget, Object param)
@@ -78,11 +134,13 @@
// test the method retrieved by Class.getMethod(String, Object[])
for (MethodDesc toTest : expectedMethods) {
String name = toTest.name();
- Method m = getTestMethod(typeUnderTest, name, param);
+ Method m = typeUnderTest.getMethod(name, argTypes(param));
testThisMethod(toTest, m, typeUnderTest, param);
}
}
+
+ // MethodHandle.invoke(): Make sure MethodHandle.invoke returns the expected value.
@Test(dataProvider = "testCasesAll",
dataProviderClass = DefaultStaticTestData.class)
public void testMethodHandleInvoke(String testTarget, Object param)
@@ -116,6 +174,7 @@
}
+ // Lookup.findStatic / .findVirtual: Make sure IllegalAccessException is thrown as expected.
@Test(dataProvider = "testClasses",
dataProviderClass = DefaultStaticTestData.class)
public void testIAE(String testTarget, Object param)
@@ -128,7 +187,7 @@
String mName = toTest.name();
Mod mod = toTest.mod();
if (mod != STATIC && typeUnderTest.isInterface()) {
- return;
+ continue;
}
Exception caught = null;
try {
@@ -136,10 +195,12 @@
} catch (Exception e) {
caught = e;
}
- assertTrue(caught != null);
+ assertNotNull(caught);
assertEquals(caught.getClass(), IllegalAccessException.class);
}
}
+
+
private static final String[] OBJECT_METHOD_NAMES = {
"equals",
"hashCode",
@@ -192,15 +253,15 @@
myMethods.put(mName, m);
}
}
- assertEquals(expectedMethods.length, myMethods.size());
+
+ assertEquals(myMethods.size(), expectedMethods.length);
for (MethodDesc toTest : expectedMethods) {
String name = toTest.name();
- Method candidate = myMethods.get(name);
+ Method candidate = myMethods.remove(name);
assertNotNull(candidate);
- myMethods.remove(name);
testThisMethod(toTest, candidate, typeUnderTest, param);
@@ -210,6 +271,7 @@
assertTrue(myMethods.isEmpty());
}
+
private void testThisMethod(MethodDesc toTest, Method method,
Class<?> typeUnderTest, Object param) throws Exception {
// Test modifiers, and invoke
@@ -256,37 +318,52 @@
assertFalse(method.isDefault());
break;
default:
- assertFalse(true); //this should never happen
+ fail(); //this should never happen
break;
}
}
+
+ private boolean isMethodDeclared(Class<?> type, String name) {
+ MethodDesc[] methDescs = type.getAnnotationsByType(MethodDesc.class);
+ for (MethodDesc desc : methDescs) {
+ if (desc.declared() == YES && desc.name().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+
+ private boolean isFoundByGetMethod(Class<?> c, String method, Class<?>... argTypes) {
+ try {
+ c.getMethod(method, argTypes);
+ return true;
+ } catch (NoSuchMethodException notFound) {
+ return false;
+ }
+ }
+
+
+ private Class<?>[] argTypes(Object param) {
+ return param == null ? new Class[0] : new Class[] { Object.class };
+ }
+
+
private Object tryInvoke(Method m, Class<?> receiverType, Object param)
throws Exception {
Object receiver = receiverType == null ? null : receiverType.newInstance();
- Object result = null;
- if (param == null) {
- result = m.invoke(receiver);
- } else {
- result = m.invoke(receiver, param);
- }
- return result;
+ Object[] args = param == null ? new Object[0] : new Object[] { param };
+ return m.invoke(receiver, args);
}
- private Method getTestMethod(Class clazz, String methodName, Object param)
- throws NoSuchMethodException {
- Class[] paramsType = (param != null)
- ? new Class[]{Object.class}
- : new Class[]{};
- return clazz.getMethod(methodName, paramsType);
- }
private MethodHandle getTestMH(Class clazz, String methodName, Object param)
throws Exception {
return getTestMH(clazz, methodName, param, false);
}
+
private MethodHandle getTestMH(Class clazz, String methodName,
Object param, boolean isNegativeTest)
throws Exception {
diff --git a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java
index ef9dec7..8049712 100644
--- a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java
+++ b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java
@@ -172,7 +172,7 @@
@MethodDesc(name = "defaultMethod", retval = "TestIF8.TestClass8", mod = DEFAULT, declared = NO)
class TestClass8<T> implements TestIF8<T> {
-};
+}
@MethodDesc(name = "defaultMethod", retval = "TestIF9.defaultMethod", mod = DEFAULT, declared = YES)
interface TestIF9 extends TestIF1 {
@@ -218,7 +218,6 @@
}
@MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = YES)
-@MethodDesc(name = "staticMethod", retval = "TestIF2.staticMethod", mod = STATIC, declared = NO)
interface TestIF12 extends TestIF2 {
default String defaultMethod() {
@@ -299,7 +298,7 @@
@MethodDesc(name = "defaultMethod", retval = "TestIF16.defaultMethod", mod = DEFAULT, declared = NO)
class TestClass16 implements TestIF16 {
-};
+}
@MethodDesc(name = "defaultMethod", retval = "TestIF17.defaultMethod", mod = DEFAULT, declared = YES)
@MethodDesc(name = "staticMethod", retval = "TestIF17.staticMethod", mod = STATIC, declared = YES)
@@ -318,6 +317,12 @@
class TestClass17 implements TestIF17 {
}
+
+@MethodDesc(name = "defaultMethod", retval = "TestIF17.defaultMethod", mod = DEFAULT, declared = NO)
+class TestClass18 extends TestClass17 {
+}
+
+
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MethodDescs.class)
@interface MethodDesc {
@@ -332,6 +337,41 @@
MethodDesc[] value();
}
+//Diamond Case for static method
+@MethodDesc(name = "staticMethod", retval = "TestIF2A.staticMethod", mod = STATIC, declared = YES)
+interface TestIF2A extends TestIF2 {
+ static String staticMethod() {
+ return "TestIF2A.staticMethod";
+ }
+}
+
+@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = YES)
+interface TestIF2B extends TestIF2 {
+ String method();
+}
+
+@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = YES)
+interface TestIF18 extends TestIF10, TestIF2A {
+ String method();
+}
+
+@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = NO)
+@MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = NO)
+interface TestIF19 extends TestIF12, TestIF2B {
+}
+
+@MethodDesc(name = "staticMethod", retval = "TestIF20.staticMethod", mod = STATIC, declared = YES)
+@MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = NO)
+interface TestIF20 extends TestIF12, TestIF2A {
+ static String staticMethod() {
+ return "TestIF20.staticMethod";
+ }
+}
+
+@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = NO)
+interface TestIF21 extends TestIF2A, TestIF2B {
+}
+
public class DefaultStaticTestData {
/**
@@ -343,22 +383,23 @@
static Object[][] testClasses() {
return new Object[][]{
{"TestClass1", null},
- //{"TestClass2", null}, @ignore due to JDK-8009411
+ {"TestClass2", null},
{"TestClass3", null},
- //{"TestClass4", null}, @ignore due to JDK-8009411
- //{"TestClass5", null}, @ignore due to JDK-8009411
- //{"TestClass6", null}, @ignore due to JDK-8009411
+ {"TestClass4", null},
+ {"TestClass5", null},
+ {"TestClass6", null},
{"TestClass7", "TestIF7.TestClass7"},
{"TestClass8", "TestIF8.TestClass8"},
{"TestClass9", null},
{"TestClass91", null},
- //{"TestClass11", null}, @ignore due to JDK-8009411
- //{"TestClass12", null}, @ignore due to JDK-8009411
+ {"TestClass11", null},
+ {"TestClass12", null},
{"TestClass13", null},
{"TestClass14", null},
{"TestClass15", null},
- {"TestClass16", null}
- //{"TestClass17", null} @ignore due to JDK-8009411
+ {"TestClass16", null},
+ {"TestClass17", null},
+ {"TestClass18", null},
};
}
@@ -372,6 +413,8 @@
return new Object[][]{
{"TestIF1", null},
{"TestIF2", null},
+ {"TestIF2A", null},
+ {"TestIF2B", null},
{"TestIF3", null},
{"TestIF4", null},
{"TestIF5", null},
@@ -388,7 +431,12 @@
{"TestIF1D", null},
{"TestIF15", null},
{"TestIF16", null},
- {"TestIF17", null},};
+ {"TestIF17", null},
+ {"TestIF18", null},
+ {"TestIF19", null},
+ {"TestIF20", null},
+ {"TestIF21", null},
+ };
}
@DataProvider
diff --git a/test/java/lang/reflect/Method/InterfaceStatic/StaticInterfaceMethodInWayOfDefault.java b/test/java/lang/reflect/Method/InterfaceStatic/StaticInterfaceMethodInWayOfDefault.java
new file mode 100644
index 0000000..ffb384f
--- /dev/null
+++ b/test/java/lang/reflect/Method/InterfaceStatic/StaticInterfaceMethodInWayOfDefault.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8009411
+ * @summary Test that a static method on an interface doesn't hide a default
+ * method with the same name and signature in a separate compilation
+ * scenario.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+import sun.misc.IOUtils;
+
+public class StaticInterfaceMethodInWayOfDefault {
+ public interface A_v1 {
+ }
+
+ public interface A_v2 {
+ default void m() {
+ System.err.println("A.m() called");
+ }
+ }
+
+ public interface B extends A_v1 {
+ static void m() {
+ System.err.println("B.m() called");
+ }
+ }
+
+ public interface C_v1 extends B {
+ default void m() {
+ System.err.println("C.m() called");
+ }
+ }
+
+ public interface C_v2 extends B {
+ }
+
+ public static class TestTask implements Callable<String> {
+ @Override
+ public String call() {
+ try {
+ Method m = C_v1.class.getMethod("m", (Class<?>[])null);
+ return m.getDeclaringClass().getSimpleName();
+ } catch (NoSuchMethodException e) {
+ System.err.println("Couldn't find method");
+ return "ERROR";
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ int errors = 0;
+ Callable<String> v1Task = new TestTask();
+
+ ClassLoader v2Loader = new V2ClassLoader(
+ StaticInterfaceMethodInWayOfDefault.class.getClassLoader());
+ Callable<String> v2Task = (Callable<String>) Class.forName(
+ TestTask.class.getName(),
+ true,
+ v2Loader).newInstance();
+
+ System.err.println("Running using _v1 classes:");
+ String res = v1Task.call();
+ if(!res.equals("C_v1")) {
+ System.err.println("Got wrong method, expecting C_v1, got: " + res);
+ errors++;
+ }
+
+ System.err.println("Running using _v2 classes:");
+ res = v2Task.call();
+ if(!res.equals("A_v1")) {
+ System.err.println("Got wrong method, expecting A_v1, got: " + res);
+ errors++;
+ }
+
+ if (errors != 0)
+ throw new RuntimeException("Errors found, check log for details");
+ }
+
+ /**
+ * A ClassLoader implementation that loads alternative implementations of
+ * classes. If class name ends with "_v1" it locates instead a class with
+ * name ending with "_v2" and loads that class instead.
+ */
+ static class V2ClassLoader extends ClassLoader {
+ V2ClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ if (name.indexOf('.') < 0) { // root package is our class
+ synchronized (getClassLoadingLock(name)) {
+ // First, check if the class has already been loaded
+ Class<?> c = findLoadedClass(name);
+ if (c == null) {
+ c = findClass(name);
+ }
+ if (resolve) {
+ resolveClass(c);
+ }
+ return c;
+ }
+ }
+ else { // not our class
+ return super.loadClass(name, resolve);
+ }
+ }
+
+ @Override
+ protected Class<?> findClass(String name)
+ throws ClassNotFoundException {
+ // special class name -> replace it with alternative name
+ if (name.endsWith("_v1")) {
+ String altName = name.substring(0, name.length() - 3) + "_v2";
+ String altPath = altName.replace('.', '/').concat(".class");
+ try (InputStream is = getResourceAsStream(altPath)) {
+ if (is != null) {
+ byte[] bytes = IOUtils.readFully(is, -1, true);
+ // patch class bytes to contain original name
+ for (int i = 0; i < bytes.length - 2; i++) {
+ if (bytes[i] == '_' &&
+ bytes[i + 1] == 'v' &&
+ bytes[i + 2] == '2') {
+ bytes[i + 2] = '1';
+ }
+ }
+ return defineClass(name, bytes, 0, bytes.length);
+ }
+ else {
+ throw new ClassNotFoundException(name);
+ }
+ }
+ catch (IOException e) {
+ throw new ClassNotFoundException(name, e);
+ }
+ }
+ else { // not special class name -> just load the class
+ String path = name.replace('.', '/').concat(".class");
+ try (InputStream is = getResourceAsStream(path)) {
+ if (is != null) {
+ byte[] bytes = IOUtils.readFully(is, -1, true);
+ return defineClass(name, bytes, 0, bytes.length);
+ }
+ else {
+ throw new ClassNotFoundException(name);
+ }
+ }
+ catch (IOException e) {
+ throw new ClassNotFoundException(name, e);
+ }
+ }
+ }
+ }
+}
diff --git a/test/java/math/BigInteger/BitLengthOverflow.java b/test/java/math/BigInteger/BitLengthOverflow.java
new file mode 100644
index 0000000..04f11b2
--- /dev/null
+++ b/test/java/math/BigInteger/BitLengthOverflow.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 6910473
+ * @summary Test that bitLength() is not negative
+ * @author Dmitry Nadezhin
+ */
+import java.math.BigInteger;
+
+public class BitLengthOverflow {
+
+ public static void main(String[] args) {
+
+ try {
+ BigInteger x = BigInteger.ONE.shiftLeft(Integer.MAX_VALUE); // x = pow(2,Integer.MAX_VALUE)
+ if (x.bitLength() != (1L << 31))
+ throw new RuntimeException("Incorrect bitLength() " + x.bitLength());
+ System.out.println("Surprisingly passed with correct bitLength() " + x.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ System.out.println("Overflow is reported by ArithmeticException, as expected");
+ } catch (OutOfMemoryError e) {
+ // possible
+ System.out.println("OutOfMemoryError");
+ }
+ }
+}
diff --git a/test/java/math/BigInteger/DivisionOverflow.java b/test/java/math/BigInteger/DivisionOverflow.java
new file mode 100644
index 0000000..b6d0d4b
--- /dev/null
+++ b/test/java/math/BigInteger/DivisionOverflow.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8022780
+ * @summary Test division of large values
+ * @author Dmitry Nadezhin
+ */
+import java.math.BigInteger;
+
+public class DivisionOverflow {
+
+ public static void main(String[] args) {
+ try {
+ BigInteger a = BigInteger.ONE.shiftLeft(2147483646);
+ BigInteger b = BigInteger.ONE.shiftLeft(1568);
+ BigInteger[] qr = a.divideAndRemainder(b);
+ BigInteger q = qr[0];
+ BigInteger r = qr[1];
+ if (!r.equals(BigInteger.ZERO))
+ throw new RuntimeException("Incorrect singum() of remainder " + r.signum());
+ if (q.bitLength() != 2147482079)
+ throw new RuntimeException("Incorrect bitLength() of quotient " + q.bitLength());
+ System.out.println("Division of large values passed without overflow.");
+ } catch (OutOfMemoryError e) {
+ // possible
+ System.out.println("OutOfMemoryError");
+ }
+ }
+}
diff --git a/test/java/math/BigInteger/DoubleValueOverflow.java b/test/java/math/BigInteger/DoubleValueOverflow.java
new file mode 100644
index 0000000..443d6ae
--- /dev/null
+++ b/test/java/math/BigInteger/DoubleValueOverflow.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8021203
+ * @summary Test that doubleValue() doesn't overflow
+ * @author Dmitry Nadezhin
+ */
+import java.math.BigInteger;
+
+public class DoubleValueOverflow {
+
+ public static void main(String[] args) {
+
+ try {
+ BigInteger x = BigInteger.valueOf(2).shiftLeft(Integer.MAX_VALUE); // x = pow(2,pow(2,31))
+ if (x.doubleValue() != Double.POSITIVE_INFINITY)
+ throw new RuntimeException("Incorrect doubleValue() " + x.doubleValue());
+ System.out.println("Passed with correct result");
+ } catch (ArithmeticException e) {
+ // expected
+ System.out.println("Overflow is reported by ArithmeticException, as expected");
+ } catch (OutOfMemoryError e) {
+ // possible
+ System.out.println("OutOfMemoryError");
+ }
+ }
+}
diff --git a/test/java/math/BigInteger/ExtremeShiftingTests.java b/test/java/math/BigInteger/ExtremeShiftingTests.java
index b64d9df..4c39a60 100644
--- a/test/java/math/BigInteger/ExtremeShiftingTests.java
+++ b/test/java/math/BigInteger/ExtremeShiftingTests.java
@@ -27,22 +27,41 @@
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
* @author Joseph D. Darcy
*/
+import java.math.BigInteger;
import static java.math.BigInteger.*;
public class ExtremeShiftingTests {
public static void main(String... args) {
+ BigInteger bi = ONE.shiftLeft(Integer.MIN_VALUE);
+ if (!bi.equals(ZERO))
+ throw new RuntimeException("1 << " + Integer.MIN_VALUE);
+
+ bi = ZERO.shiftLeft(Integer.MIN_VALUE);
+ if (!bi.equals(ZERO))
+ throw new RuntimeException("0 << " + Integer.MIN_VALUE);
+
+ bi = BigInteger.valueOf(-1);
+ bi = bi.shiftLeft(Integer.MIN_VALUE);
+ if (!bi.equals(BigInteger.valueOf(-1)))
+ throw new RuntimeException("-1 << " + Integer.MIN_VALUE);
+
try {
- ONE.shiftLeft(Integer.MIN_VALUE);
- throw new RuntimeException("Should not reach here.");
+ ONE.shiftRight(Integer.MIN_VALUE);
+ throw new RuntimeException("1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) {
; // Expected
}
+ bi = ZERO.shiftRight(Integer.MIN_VALUE);
+ if (!bi.equals(ZERO))
+ throw new RuntimeException("0 >> " + Integer.MIN_VALUE);
+
try {
- ONE.shiftRight(Integer.MIN_VALUE);
- throw new RuntimeException("Should not reach here.");
+ BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE);
+ throw new RuntimeException("-1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) {
; // Expected
}
+
}
}
diff --git a/test/java/math/BigInteger/StringConstructorOverflow.java b/test/java/math/BigInteger/StringConstructorOverflow.java
new file mode 100644
index 0000000..ac362d0
--- /dev/null
+++ b/test/java/math/BigInteger/StringConstructorOverflow.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8021204
+ * @summary Test constructor BigInteger(String val, int radix) on very long string
+ * @author Dmitry Nadezhin
+ */
+import java.math.BigInteger;
+
+public class StringConstructorOverflow {
+
+ // String with hexadecimal value pow(2,pow(2,34))+1
+ private static String makeLongHexString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append('1');
+ for (int i = 0; i < (1 << 30) - 1; i++) {
+ sb.append('0');
+ }
+ sb.append('1');
+ return sb.toString();
+ }
+
+ public static void main(String[] args) {
+ try {
+ BigInteger bi = new BigInteger(makeLongHexString(), 16);
+ if (bi.compareTo(BigInteger.ONE) <= 0)
+ throw new RuntimeException("Incorrect result " + bi.toString());
+ } catch (ArithmeticException e) {
+ // expected
+ System.out.println("Overflow is reported by ArithmeticException, as expected");
+ } catch (OutOfMemoryError e) {
+ // possible
+ System.out.println("OutOfMemoryError");
+ System.out.println("Run jtreg with -javaoption:-Xmx8g");
+ }
+ }
+}
diff --git a/test/java/math/BigInteger/SymmetricRangeTests.java b/test/java/math/BigInteger/SymmetricRangeTests.java
new file mode 100644
index 0000000..abded05
--- /dev/null
+++ b/test/java/math/BigInteger/SymmetricRangeTests.java
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test is intentionally ignored because of huge memory requirements
+ * @ test
+ * @run main/timeout=180/othervm -Xmx8g SymmetricRangeTests
+ * @bug 6910473 8021204 8021203 9005933
+ * @summary Test range of BigInteger values
+ * @author Dmitry Nadezhin
+ */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Random;
+import java.math.BigInteger;
+
+public class SymmetricRangeTests {
+
+ private static final BigInteger MAX_VALUE = makeMaxValue();
+ private static final BigInteger MIN_VALUE = MAX_VALUE.negate();
+
+ private static BigInteger makeMaxValue() {
+ byte[] ba = new byte[1 << 28];
+ Arrays.fill(ba, (byte) 0xFF);
+ ba[0] = (byte) 0x7F;
+ return new BigInteger(ba);
+ }
+
+ private static void check(String msg, BigInteger actual, BigInteger expected) {
+ if (!actual.equals(expected)) {
+ throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
+ }
+ }
+
+ private static void check(String msg, double actual, double expected) {
+ if (actual != expected) {
+ throw new RuntimeException(msg + "=" + actual);
+ }
+ }
+
+ private static void check(String msg, float actual, float expected) {
+ if (actual != expected) {
+ throw new RuntimeException(msg + "=" + actual);
+ }
+ }
+
+ private static void check(String msg, long actual, long expected) {
+ if (actual != expected) {
+ throw new RuntimeException(msg + "=" + actual);
+ }
+ }
+
+ private static void check(String msg, int actual, int expected) {
+ if (actual != expected) {
+ throw new RuntimeException(msg + "=" + actual);
+ }
+ }
+
+ private static void testOverflowInMakePositive() {
+ System.out.println("Testing overflow in BigInteger.makePositive");
+ byte[] ba = new byte[Integer.MAX_VALUE - 2];
+ ba[0] = (byte) 0x80;
+ try {
+ BigInteger actual = new BigInteger(ba);
+ throw new RuntimeException("new BigInteger(ba).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testBug8021204() {
+ System.out.println("Testing Bug 8021204");
+ StringBuilder sb = new StringBuilder();
+ sb.append('1');
+ for (int i = 0; i < (1 << 30) - 1; i++) {
+ sb.append('0');
+ }
+ sb.append('1');
+ String s = sb.toString();
+ sb = null;
+ try {
+ BigInteger actual = new BigInteger(s, 16);
+ throw new RuntimeException("new BigInteger(\"1000...001\").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testOverflowInBitSieve() {
+ System.out.println("Testing overflow in BitSieve.sieveSingle");
+ int bitLength = (5 << 27) - 1;
+ try {
+ Random rnd = new Random();
+ BigInteger actual = new BigInteger(bitLength, 0, rnd);
+ throw new RuntimeException("new BigInteger(bitLength, 0, null).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger bi = BigInteger.ONE.shiftLeft(bitLength - 1).subtract(BigInteger.ONE);
+ BigInteger actual = bi.nextProbablePrime();
+ throw new RuntimeException("bi.nextActualPrime().bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testAdd() {
+ System.out.println("Testing BigInteger.add");
+ try {
+ BigInteger actual = MAX_VALUE.add(BigInteger.ONE);
+ throw new RuntimeException("BigInteger.MAX_VALUE.add(BigInteger.ONE).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testSubtract() {
+ System.out.println("Testing BigInteger.subtract");
+ try {
+ BigInteger actual = MIN_VALUE.subtract(BigInteger.ONE);
+ throw new RuntimeException("BigInteger.MIN_VALUE.subtract(BigInteger.ONE).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testMultiply() {
+ System.out.println("Testing BigInteger.multiply");
+ int py = 2000;
+ int px = Integer.MAX_VALUE - py;
+ BigInteger x = BigInteger.ONE.shiftLeft(px);
+ BigInteger y = BigInteger.ONE.shiftLeft(py);
+ try {
+ BigInteger actual = x.multiply(y);
+ throw new RuntimeException("(1 << " + px + " ) * (1 << " + py + ").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testDivide() {
+ System.out.println("Testing BigInteger.divide");
+ check("BigInteger.MIN_VALUE.divide(BigInteger.valueOf(-1))",
+ MIN_VALUE.divide(BigInteger.valueOf(-1)), MAX_VALUE);
+ check("BigInteger.MIN_VALUE.divide(BigInteger.ONE)",
+ MIN_VALUE.divide(BigInteger.ONE), MIN_VALUE);
+ }
+
+ private static void testDivideAndRemainder(String msg, BigInteger dividend, BigInteger divisor,
+ BigInteger expectedQuotent, BigInteger expectedRemainder) {
+ BigInteger[] qr = dividend.divideAndRemainder(divisor);
+ check(msg + "[0]", qr[0], expectedQuotent);
+ check(msg + "[1]", qr[1], expectedRemainder);
+ }
+
+ private static void testDivideAndRemainder() {
+ System.out.println("Testing BigInteger.divideAndRemainder");
+ testDivideAndRemainder("BigInteger.MIN_VALUE.divideAndRemainder(BigInteger.valueOf(-1))",
+ MIN_VALUE, BigInteger.valueOf(-1),
+ MAX_VALUE,
+ BigInteger.ZERO);
+ }
+
+ private static void testBug9005933() {
+ System.out.println("Testing Bug 9005933");
+ int dividendPow = 2147483646;
+ int divisorPow = 1568;
+ BigInteger dividend = BigInteger.ONE.shiftLeft(dividendPow);
+ BigInteger divisor = BigInteger.ONE.shiftLeft(divisorPow);
+ testDivideAndRemainder("(1 << " + dividendPow + ").divideAndRemainder(1 << " + divisorPow + ")",
+ dividend, divisor,
+ BigInteger.ONE.shiftLeft(dividendPow - divisorPow),
+ BigInteger.ZERO);
+ }
+
+ private static void testRemainder() {
+ System.out.println("Testing BigInteger.remainder");
+ check("BigInteger.MIN_VALUE.remainder(BigInteger.valueOf(-1))",
+ MIN_VALUE.remainder(BigInteger.valueOf(-1)), BigInteger.ZERO);
+ }
+
+ private static void testPow() {
+ System.out.println("Testing BigInteger.pow");
+ check("BigInteger.MIN_VALUE.pow(1)",
+ MIN_VALUE.pow(1), MIN_VALUE);
+ try {
+ BigInteger actual = BigInteger.valueOf(4).pow(Integer.MAX_VALUE);
+ throw new RuntimeException("BigInteger.valueOf(4).pow(Integer.MAX_VALUE).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testGcd() {
+ System.out.println("Testing BigInteger.gcd");
+ check("BigInteger.MIN_VALUE.gcd(BigInteger.MIN_VALUE)",
+ MIN_VALUE.gcd(MIN_VALUE), MAX_VALUE);
+ check("BigInteger.MIN_VALUE.gcd(BigInteger.ZERO)",
+ MIN_VALUE.gcd(BigInteger.ZERO), MAX_VALUE);
+ check("BigInteger.ZERO.gcd(MIN_VALUE)",
+ BigInteger.ZERO.gcd(MIN_VALUE), MAX_VALUE);
+ }
+
+ private static void testAbs() {
+ System.out.println("Testing BigInteger.abs");
+ check("BigInteger.MIN_VALUE.abs()",
+ MIN_VALUE.abs(), MAX_VALUE);
+ check("BigInteger.MAX_VALUE.abs()",
+ MAX_VALUE.abs(), MAX_VALUE);
+ }
+
+ private static void testNegate() {
+ System.out.println("Testing BigInteger.negate");
+ check("BigInteger.MIN_VALUE.negate()",
+ MIN_VALUE.negate(), MAX_VALUE);
+ check("BigInteger.MAX_VALUE.negate()",
+ MAX_VALUE.negate(), MIN_VALUE);
+ }
+
+ private static void testMod() {
+ System.out.println("Testing BigInteger.mod");
+ check("BigInteger.MIN_VALUE.mod(BigInteger.MAX_VALUE)",
+ MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
+ check("BigInteger.MAX_VALUE.mod(BigInteger.MAX_VALUE)",
+ MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO);
+ }
+
+ private static void testModPow() {
+ System.out.println("Testing BigInteger.modPow");
+ BigInteger x = BigInteger.valueOf(3);
+ BigInteger m = BigInteger.valueOf(-4).subtract(MIN_VALUE);
+ check("BigInteger.valueOf(3).modPow(BigInteger.ONE, m)",
+ x.modPow(BigInteger.ONE, m), x);
+ }
+
+ // slow test
+ private static void testModInverse() {
+ System.out.println("Testing BigInteger.modInverse");
+ check("BigInteger.MIN_VALUE.modInverse(BigInteger.MAX_VALUE)",
+ MIN_VALUE.modInverse(MAX_VALUE), MAX_VALUE.subtract(BigInteger.ONE));
+ }
+
+ private static void testShiftLeft() {
+ System.out.println("Testing BigInteger.shiftLeft");
+ try {
+ BigInteger actual = MIN_VALUE.shiftLeft(1);
+ throw new RuntimeException("BigInteger.MIN_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = MAX_VALUE.shiftLeft(1);
+ throw new RuntimeException("BigInteger.MAX_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testShiftRight() {
+ System.out.println("Testing BigInteger.shiftRight");
+ try {
+ BigInteger actual = MIN_VALUE.shiftRight(-1);
+ throw new RuntimeException("BigInteger.MIN_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = MAX_VALUE.shiftRight(-1);
+ throw new RuntimeException("BigInteger.MAX_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testAnd() {
+ System.out.println("Testing BigInteger.and");
+ check("BigInteger.MIN_VALUE.and(BigInteger.MIN_VALUE)",
+ MIN_VALUE.and(MIN_VALUE), MIN_VALUE);
+ check("BigInteger.MAX_VALUE.and(BigInteger.MAX_VALUE)",
+ MAX_VALUE.and(MAX_VALUE), MAX_VALUE);
+ check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
+ MIN_VALUE.and(MAX_VALUE), BigInteger.ONE);
+ try {
+ BigInteger actual = MIN_VALUE.and(BigInteger.valueOf(-2));
+ throw new RuntimeException("BigInteger.MIN_VALUE.and(-2)).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testOr() {
+ System.out.println("Testing BigInteger.or");
+ check("BigInteger.MIN_VALUE.or(BigInteger.MIN_VALUE)",
+ MIN_VALUE.or(MIN_VALUE), MIN_VALUE);
+ check("BigInteger.MAX_VALUE.or(BigInteger.MAX_VALUE)",
+ MAX_VALUE.or(MAX_VALUE), MAX_VALUE);
+ check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)",
+ MIN_VALUE.or(MAX_VALUE), BigInteger.valueOf(-1));
+ }
+
+ private static void testXor() {
+ System.out.println("Testing BigInteger.xor");
+ check("BigInteger.MIN_VALUE.xor(BigInteger.MIN_VALUE)",
+ MIN_VALUE.xor(MIN_VALUE), BigInteger.ZERO);
+ check("BigInteger.MAX_VALUE.xor(BigInteger.MAX_VALUE)",
+ MAX_VALUE.xor(MAX_VALUE), BigInteger.ZERO);
+ check("BigInteger.MIN_VALUE.xor(BigInteger.MAX_VALUE)",
+ MIN_VALUE.xor(MAX_VALUE), BigInteger.valueOf(-2));
+ try {
+ BigInteger actual = MIN_VALUE.xor(BigInteger.ONE);
+ throw new RuntimeException("BigInteger.MIN_VALUE.xor(BigInteger.ONE)).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testNot() {
+ System.out.println("Testing BigInteger.not");
+ check("BigInteger.MIN_VALUE.not()",
+ MIN_VALUE.not(), MAX_VALUE.subtract(BigInteger.ONE));
+ try {
+ BigInteger actual = MAX_VALUE.not();
+ throw new RuntimeException("BigInteger.MAX_VALUE.not()).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testSetBit() {
+ System.out.println("Testing BigInteger.setBit");
+ check("BigInteger.MIN_VALUE.setBit(" + Integer.MAX_VALUE + ")",
+ MIN_VALUE.setBit(Integer.MAX_VALUE), MIN_VALUE);
+ try {
+ BigInteger actual = MAX_VALUE.setBit(Integer.MAX_VALUE);
+ throw new RuntimeException("BigInteger.MAX_VALUE.setBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testClearBit() {
+ System.out.println("Testing BigInteger.clearBit");
+ check("BigInteger.MAX_VALUE.clearBit(" + Integer.MAX_VALUE + ")",
+ MAX_VALUE.clearBit(Integer.MAX_VALUE), MAX_VALUE);
+ try {
+ BigInteger actual = MIN_VALUE.clearBit(Integer.MAX_VALUE);
+ throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = MIN_VALUE.clearBit(0);
+ throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(0).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testFlipBit() {
+ System.out.println("Testing BigInteger.flipBit");
+ try {
+ BigInteger actual = MIN_VALUE.flipBit(Integer.MAX_VALUE);
+ throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = MIN_VALUE.flipBit(0);
+ throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(0).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = MAX_VALUE.flipBit(Integer.MAX_VALUE);
+ throw new RuntimeException("BigInteger.MAX_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testGetLowestSetBit() {
+ System.out.println("Testing BigInteger.getLowestSetBit");
+ check("BigInteger.MIN_VALUE.getLowestSetBit()",
+ MIN_VALUE.getLowestSetBit(), 0);
+ check("BigInteger.MAX_VALUE.getLowestSetBit()",
+ MAX_VALUE.getLowestSetBit(), 0);
+ }
+
+ private static void testBitLength() {
+ System.out.println("Testing BigInteger.bitLength");
+ check("BigInteger.MIN_NEXT.bitLength()",
+ MIN_VALUE.bitLength(), Integer.MAX_VALUE);
+ check("BigInteger.MAX_VALUE.bitLength()",
+ MAX_VALUE.bitLength(), Integer.MAX_VALUE);
+ }
+
+ private static void testBitCount() {
+ System.out.println("Testing BigInteger.bitCount");
+ check("BigInteger.MIN_VALUE.bitCount()",
+ MIN_VALUE.bitCount(), Integer.MAX_VALUE - 1);
+ check("BigInteger.MAX_VALUE.bitCount()",
+ MAX_VALUE.bitCount(), Integer.MAX_VALUE);
+ }
+
+ private static void testToString(String msg, int radix, BigInteger bi, int length, String startsWith, char c) {
+ String s = bi.toString(radix);
+ if (s.length() != length) {
+ throw new RuntimeException(msg + ".length=" + s.length());
+ }
+ if (!s.startsWith(startsWith)) {
+ throw new RuntimeException(msg + "[0]=" + s.substring(0, startsWith.length()));
+ }
+ for (int i = startsWith.length(); i < s.length(); i++) {
+ if (s.charAt(i) != c) {
+ throw new RuntimeException(msg + "[" + i + "]='" + s.charAt(i) + "'");
+ }
+ }
+ }
+
+ private static void testToString() {
+ System.out.println("Testing BigInteger.toString");
+ testToString("BigInteger.MIN_VALUE.toString(16)=", 16,
+ BigInteger.valueOf(-1).shiftLeft(Integer.MAX_VALUE - 1),
+ (1 << 29) + 1, "-4", '0');
+ }
+
+ private static void testToByteArrayWithConstructor(String msg, BigInteger bi, int length, byte msb, byte b, byte lsb) {
+ byte[] ba = bi.toByteArray();
+ if (ba.length != length) {
+ throw new RuntimeException(msg + ".length=" + ba.length);
+ }
+ if (ba[0] != msb) {
+ throw new RuntimeException(msg + "[0]=" + ba[0]);
+ }
+ for (int i = 1; i < ba.length - 1; i++) {
+ if (ba[i] != b) {
+ throw new RuntimeException(msg + "[" + i + "]=" + ba[i]);
+ }
+ }
+ if (ba[ba.length - 1] != lsb) {
+ throw new RuntimeException(msg + "[" + (ba.length - 1) + "]=" + ba[ba.length - 1]);
+ }
+ BigInteger actual = new BigInteger(ba);
+ if (!actual.equals(bi)) {
+ throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
+ }
+ }
+
+ private static void testToByteArrayWithConstructor() {
+ System.out.println("Testing BigInteger.toByteArray with constructor");
+ testToByteArrayWithConstructor("BigInteger.MIN_VALUE.toByteArray()",
+ MIN_VALUE, (1 << 28), (byte) 0x80, (byte) 0x00, (byte) 0x01);
+ testToByteArrayWithConstructor("BigInteger.MAX_VALUE.toByteArray()",
+ MAX_VALUE, (1 << 28), (byte) 0x7f, (byte) 0xff, (byte) 0xff);
+
+ byte[] ba = new byte[1 << 28];
+ ba[0] = (byte) 0x80;
+ try {
+ BigInteger actual = new BigInteger(-1, ba);
+ throw new RuntimeException("new BigInteger(-1, ba).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ try {
+ BigInteger actual = new BigInteger(1, ba);
+ throw new RuntimeException("new BigInteger(1, ba).bitLength()=" + actual.bitLength());
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ private static void testIntValue() {
+ System.out.println("Testing BigInteger.intValue");
+ check("BigInteger.MIN_VALUE.intValue()",
+ MIN_VALUE.intValue(), 1);
+ check("BigInteger.MAX_VALUE.floatValue()",
+ MAX_VALUE.intValue(), -1);
+ }
+
+ private static void testLongValue() {
+ System.out.println("Testing BigInteger.longValue");
+ check("BigInteger.MIN_VALUE.longValue()",
+ MIN_VALUE.longValue(), 1L);
+ check("BigInteger.MAX_VALUE.longValue()",
+ MAX_VALUE.longValue(), -1L);
+ }
+
+ private static void testFloatValue() {
+ System.out.println("Testing BigInteger.floatValue, Bug 8021203");
+ check("BigInteger.MIN_VALUE_.floatValue()",
+ MIN_VALUE.floatValue(), Float.NEGATIVE_INFINITY);
+ check("BigInteger.MAX_VALUE.floatValue()",
+ MAX_VALUE.floatValue(), Float.POSITIVE_INFINITY);
+ }
+
+ private static void testDoubleValue() {
+ System.out.println("Testing BigInteger.doubleValue, Bug 8021203");
+ check("BigInteger.MIN_VALUE.doubleValue()",
+ MIN_VALUE.doubleValue(), Double.NEGATIVE_INFINITY);
+ check("BigInteger.MAX_VALUE.doubleValue()",
+ MAX_VALUE.doubleValue(), Double.POSITIVE_INFINITY);
+ }
+
+ private static void testSerialization(String msg, BigInteger bi) {
+ try {
+ ByteArrayOutputStream baOut = new ByteArrayOutputStream((1 << 28) + 1000);
+ ObjectOutputStream out = new ObjectOutputStream(baOut);
+ out.writeObject(bi);
+ out.close();
+ out = null;
+ byte[] ba = baOut.toByteArray();
+ baOut = null;
+ ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));
+ BigInteger actual = (BigInteger) in.readObject();
+ if (!actual.equals(bi)) {
+ throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength());
+ }
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException(msg + " raised exception ", e);
+ }
+ }
+
+ private static void testSerialization() {
+ System.out.println("Testing BigInteger serialization");
+ testSerialization("BigInteger.MIN_VALUE.intValue()",
+ MIN_VALUE);
+ testSerialization("BigInteger.MAX_VALUE.floatValue()",
+ MAX_VALUE);
+ }
+
+ private static void testLongValueExact() {
+ System.out.println("Testing BigInteger.longValueExact");
+ try {
+ long actual = MIN_VALUE.longValueExact();
+ throw new RuntimeException("BigInteger.MIN_VALUE.longValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ try {
+ long actual = MAX_VALUE.longValueExact();
+ throw new RuntimeException("BigInteger.MAX_VALUE.longValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ }
+
+ private static void testIntValueExact() {
+ System.out.println("Testing BigInteger.intValueExact");
+ try {
+ long actual = MIN_VALUE.intValueExact();
+ throw new RuntimeException("BigInteger.MIN_VALUE.intValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ try {
+ long actual = MAX_VALUE.intValueExact();
+ throw new RuntimeException("BigInteger.MAX_VALUE.intValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ }
+
+ private static void testShortValueExact() {
+ System.out.println("Testing BigInteger.shortValueExact");
+ try {
+ long actual = MIN_VALUE.shortValueExact();
+ throw new RuntimeException("BigInteger.MIN_VALUE.shortValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ try {
+ long actual = MAX_VALUE.shortValueExact();
+ throw new RuntimeException("BigInteger.MAX_VALUE.shortValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ }
+
+ private static void testByteValueExact() {
+ System.out.println("Testing BigInteger.byteValueExact");
+ try {
+ long actual = MIN_VALUE.byteValueExact();
+ throw new RuntimeException("BigInteger.MIN_VALUE.byteValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ try {
+ long actual = MAX_VALUE.byteValueExact();
+ throw new RuntimeException("BigInteger.MAX_VALUE.byteValueExact()= " + actual);
+ } catch (ArithmeticException e) {
+ // excpected
+ }
+ }
+
+ public static void main(String... args) {
+ testOverflowInMakePositive();
+ testBug8021204();
+ testOverflowInBitSieve();
+ testAdd();
+ testSubtract();
+ testMultiply();
+ testDivide();
+ testDivideAndRemainder();
+ testBug9005933();
+ testRemainder();
+ testPow();
+ testGcd();
+ testAbs();
+ testNegate();
+ testMod();
+ testModPow();
+// testModInverse();
+ testShiftLeft();
+ testShiftRight();
+ testAnd();
+ testOr();
+ testXor();
+ testNot();
+ testSetBit();
+ testClearBit();
+ testFlipBit();
+ testGetLowestSetBit();
+ testBitLength();
+ testBitCount();
+ testToString();
+ testToByteArrayWithConstructor();
+ testIntValue();
+ testLongValue();
+ testFloatValue();
+ testDoubleValue();
+ testSerialization();
+ testLongValueExact();
+ testIntValueExact();
+ testShortValueExact();
+ testByteValueExact();
+ }
+}
diff --git a/test/java/net/Authenticator/B4769350.java b/test/java/net/Authenticator/B4769350.java
index 23987c7..e6cdaa1 100644
--- a/test/java/net/Authenticator/B4769350.java
+++ b/test/java/net/Authenticator/B4769350.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -23,9 +23,7 @@
/**
* @test
- * @bug 4769350
- * @library ../../../sun/net/www/httptest/
- * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction AbstractCallback
+ * @bug 4769350 8017779
* @run main/othervm B4769350 server
* @run main/othervm B4769350 proxy
* @summary proxy authentication username and password caching only works in serial case
@@ -34,8 +32,17 @@
* tests may already have invoked the HTTP handler.
*/
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
import java.io.*;
import java.net.*;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
public class B4769350 {
@@ -43,13 +50,12 @@
static boolean error = false;
static void read (InputStream is) throws IOException {
- int c;
- while ((c=is.read()) != -1) {
+ while (is.read() != -1) {
//System.out.write (c);
}
}
- static class Client extends Thread {
+ static class Client extends Thread {
String authority, path;
boolean allowerror;
@@ -64,8 +70,8 @@
try {
URI u = new URI ("http", authority, path, null, null);
URL url = u.toURL();
- URLConnection urlc = url.openConnection ();
- InputStream is = urlc.getInputStream ();
+ URLConnection urlc = url.openConnection();
+ InputStream is = urlc.getInputStream();
read (is);
is.close();
} catch (URISyntaxException e) {
@@ -73,7 +79,8 @@
error = true;
} catch (IOException e) {
if (!allowerror) {
- System.out.println (Thread.currentThread().getName() + " " + e);
+ System.out.println (Thread.currentThread().getName()
+ + " " + e);
e.printStackTrace();
error = true;
}
@@ -81,55 +88,58 @@
}
}
- static class CallBack extends AbstractCallback {
+ class Server implements AutoCloseable {
+ HttpServer server;
+ Executor executor;
+ CyclicBarrier t1Cond1;
+ CyclicBarrier t1Cond2;
- void errorReply (HttpTransaction req, String reply) throws IOException {
- req.addResponseHeader ("Connection", "close");
- req.addResponseHeader ("WWW-Authenticate", reply);
- req.sendResponse (401, "Unauthorized");
- req.orderlyClose();
+ public String getAddress() {
+ return server.getAddress().getHostName();
}
- void proxyReply (HttpTransaction req, String reply) throws IOException {
- req.addResponseHeader ("Proxy-Authenticate", reply);
- req.sendResponse (407, "Proxy Authentication Required");
- }
+ public void startServer() {
+ InetSocketAddress addr = new InetSocketAddress(0);
- void okReply (HttpTransaction req) throws IOException {
- req.addResponseHeader ("Connection", "close");
- req.setResponseEntityBody ("Hello .");
- req.sendResponse (200, "Ok");
- req.orderlyClose();
- }
-
- public void request (HttpTransaction req, int count) {
try {
- URI uri = req.getRequestURI();
- String path = uri.getPath();
- if (path.endsWith ("/t1a")) {
- doT1a (req, count);
- } else if (path.endsWith ("/t1b")) {
- doT1b (req, count);
- } else if (path.endsWith ("/t1c")) {
- doT1c (req, count);
- } else if (path.endsWith ("/t1d")) {
- doT1d (req, count);
- } else if (path.endsWith ("/t2a")) {
- doT2a (req, count);
- } else if (path.endsWith ("/t2b")) {
- doT2b (req, count);
- } else if (path.endsWith ("/t3a")) {
- doT3a (req, count);
- } else if (path.endsWith ("/t3b")) {
- doT3bc (req, count);
- } else if (path.endsWith ("/t3c")) {
- doT3bc (req, count);
- } else {
- System.out.println ("unexpected request URI");
- }
- } catch (IOException e) {
- e.printStackTrace();
+ server = HttpServer.create(addr, 0);
+ } catch (IOException ioe) {
+ throw new RuntimeException("Server could not be created");
}
+ executor = Executors.newFixedThreadPool(10);
+ server.setExecutor(executor);
+ server.createContext("/test/realm1/t1a",
+ new AuthenticationHandlerT1a() );
+ server.createContext("/test/realm2/t1b",
+ new AuthenticationHandlerT1b());
+ server.createContext("/test/realm1/t1c",
+ new AuthenticationHandlerT1c());
+ server.createContext("/test/realm2/t1d",
+ new AuthenticationHandlerT1d());
+ server.createContext("/test/realm3/t2a",
+ new AuthenticationHandlerT2a());
+ server.createContext("/test/realm3/t2b",
+ new AuthenticationHandlerT2b());
+ server.createContext("/test/realm4/t3a",
+ new AuthenticationHandlerT3a());
+ server.createContext("/test/realm4/t3b",
+ new AuthenticationHandlerT3bc());
+ server.createContext("/test/realm4/t3c",
+ new AuthenticationHandlerT3bc());
+ t1Cond1 = new CyclicBarrier(2);
+ t1Cond2 = new CyclicBarrier(2);
+ server.start();
+ }
+
+ public int getPort() {
+ return server.getAddress().getPort();
+ }
+
+ public void close() {
+ if (executor != null)
+ ((ExecutorService)executor).shutdownNow();
+ if (server != null)
+ server.stop(0);
}
/* T1 tests the client by sending 4 requests to 2 different realms
@@ -138,90 +148,158 @@
* the second requests should be executed without calling the authenticator.
* The test succeeds if the authenticator was only called twice.
*/
- void doT1a (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- errorReply (req, "Basic realm=\"realm1\"");
- TestHttpServer.rendezvous ("one", 2);
- break;
- case 1:
- TestHttpServer.waitForCondition ("cond2");
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ class AuthenticationHandlerT1a implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ try {
+ switch(count) {
+ case 0:
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm1\"");
+ break;
+ case 1:
+ t1Cond1.await();
+ t1cond2latch.await();
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
+ } catch (InterruptedException |
+ BrokenBarrierException e)
+ {
+ throw new RuntimeException(e);
+ }
}
}
+ class AuthenticationHandlerT1b implements HttpHandler
+ {
+ volatile int count = -1;
- void doT1b (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- errorReply (req, "Basic realm=\"realm2\"");
- TestHttpServer.rendezvous ("one", 2);
- TestHttpServer.setCondition ("cond1");
- break;
- case 1:
- TestHttpServer.waitForCondition ("cond2");
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ try {
+ switch(count) {
+ case 0:
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm2\"");
+ break;
+ case 1:
+ t1Cond1.await();
+ t1cond1latch.countDown();
+ t1cond2latch.await();
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
+ } catch (InterruptedException | BrokenBarrierException e) {
+ throw new RuntimeException(e);
+ }
}
}
- void doT1c (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- errorReply (req, "Basic realm=\"realm1\"");
- TestHttpServer.rendezvous ("two", 2);
- break;
- case 1:
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ class AuthenticationHandlerT1c implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ switch(count) {
+ case 0:
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm1\"");
+ try {
+ t1Cond2.await();
+ } catch (InterruptedException |
+ BrokenBarrierException e)
+ {
+ throw new RuntimeException(e);
+ }
+ break;
+ case 1:
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
}
}
- void doT1d (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- errorReply (req, "Basic realm=\"realm2\"");
- TestHttpServer.rendezvous ("two", 2);
- TestHttpServer.setCondition ("cond2");
- break;
- case 1:
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ class AuthenticationHandlerT1d implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ switch(count) {
+ case 0:
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm2\"");
+ try {
+ t1Cond2.await();
+ } catch (InterruptedException |
+ BrokenBarrierException e)
+ {
+ throw new RuntimeException(e);
+ }
+ t1cond2latch.countDown();
+ break;
+ case 1:
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
}
}
-
/* T2 tests to check that if initial authentication fails, the second will
* succeed, and the authenticator is called twice
*/
- void doT2a (HttpTransaction req, int count) throws IOException {
- /* This will be called several times */
- if (count == 1) {
- TestHttpServer.setCondition ("T2cond1");
+ class AuthenticationHandlerT2a implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ if (count == 1) {
+ t2condlatch.countDown();
+ }
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm3\"");
+
}
- errorReply (req, "Basic realm=\"realm3\"");
}
- void doT2b (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- errorReply (req, "Basic realm=\"realm3\"");
- break;
- case 1:
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ class AuthenticationHandlerT2b implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ switch(count) {
+ case 0:
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm3\"");
+ break;
+ case 1:
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
}
}
@@ -229,63 +307,117 @@
* resource at same time. Authenticator should be called once for server
* and once for proxy
*/
- void doT3a (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- proxyReply (req, "Basic realm=\"proxy\"");
- TestHttpServer.setCondition ("T3cond1");
- break;
- case 1:
- errorReply (req, "Basic realm=\"realm4\"");
- break;
- case 2:
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+
+ class AuthenticationHandlerT3a implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ switch(count) {
+ case 0:
+ AuthenticationHandler.proxyReply(exchange,
+ "Basic realm=\"proxy\"");
+ break;
+ case 1:
+ t3cond1.countDown();
+ AuthenticationHandler.errorReply(exchange,
+ "Basic realm=\"realm4\"");
+ break;
+ case 2:
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
}
}
- void doT3bc (HttpTransaction req, int count) throws IOException {
- switch (count) {
- case 0:
- proxyReply (req, "Basic realm=\"proxy\"");
- break;
- case 1:
- okReply (req);
- break;
- default:
- System.out.println ("Unexpected request");
+ class AuthenticationHandlerT3bc implements HttpHandler
+ {
+ volatile int count = -1;
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ count++;
+ switch(count) {
+ case 0:
+ AuthenticationHandler.proxyReply(exchange,
+ "Basic realm=\"proxy\"");
+ break;
+ case 1:
+ AuthenticationHandler.okReply(exchange);
+ break;
+ default:
+ System.out.println ("Unexpected request");
+ }
}
}
- };
+ }
- static TestHttpServer server;
+ static class AuthenticationHandler {
+ static void errorReply(HttpExchange exchange, String reply)
+ throws IOException
+ {
+ exchange.getResponseHeaders().add("Connection", "close");
+ exchange.getResponseHeaders().add("WWW-Authenticate", reply);
+ exchange.sendResponseHeaders(401, 0);
+ exchange.close();
+ }
+
+ static void proxyReply (HttpExchange exchange, String reply)
+ throws IOException
+ {
+ exchange.getResponseHeaders().add("Proxy-Authenticate", reply);
+ exchange.sendResponseHeaders(407, 0);
+ }
+
+ static void okReply (HttpExchange exchange) throws IOException {
+ exchange.getResponseHeaders().add("Connection", "close");
+ String response = "Hello .";
+ exchange.sendResponseHeaders(200, response.getBytes().length);
+ OutputStream os = exchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ exchange.close();
+ }
+ }
+
+ static Server server;
static MyAuthenticator auth = new MyAuthenticator ();
static int redirects = 4;
static Client c1,c2,c3,c4,c5,c6,c7,c8,c9;
- static void doServerTests (String authority) throws Exception {
+ static CountDownLatch t1cond1latch;
+ static CountDownLatch t1cond2latch;
+ static CountDownLatch t2condlatch;
+ static CountDownLatch t3cond1;
+
+ static void doServerTests (String authority, Server server) throws Exception
+ {
System.out.println ("Doing Server tests");
System.out.println ("T1");
c1 = new Client (authority, "/test/realm1/t1a", false);
c2 = new Client (authority, "/test/realm2/t1b", false);
c3 = new Client (authority, "/test/realm1/t1c", false);
c4 = new Client (authority, "/test/realm2/t1d", false);
-
+ t1cond1latch = new CountDownLatch(1);
+ t1cond2latch = new CountDownLatch(1);
c1.start(); c2.start();
- TestHttpServer.waitForCondition ("cond1");
+ t1cond1latch.await();
c3.start(); c4.start();
c1.join(); c2.join(); c3.join(); c4.join();
int f = auth.getCount();
if (f != 2) {
- except ("Authenticator was called "+f+" times. Should be 2");
+ except ("Authenticator was called "+f+" times. Should be 2",
+ server);
}
if (error) {
- except ("error occurred");
+ except ("error occurred", server);
}
auth.resetCount();
@@ -293,73 +425,71 @@
c5 = new Client (authority, "/test/realm3/t2a", true);
c6 = new Client (authority, "/test/realm3/t2b", false);
+ t2condlatch = new CountDownLatch(1);
c5.start ();
- TestHttpServer.waitForCondition ("T2cond1");
+ t2condlatch.await();
c6.start ();
c5.join(); c6.join();
f = auth.getCount();
if (f != redirects+1) {
- except ("Authenticator was called "+f+" times. Should be: " + redirects+1);
+ except ("Authenticator was called "+f+" times. Should be: "
+ + redirects+1, server);
}
if (error) {
- except ("error occurred");
+ except ("error occurred", server);
}
}
- static void doProxyTests (String authority) throws Exception {
+ static void doProxyTests (String authority, Server server) throws Exception
+ {
System.out.println ("Doing Proxy tests");
c7 = new Client (authority, "/test/realm4/t3a", false);
c8 = new Client (authority, "/test/realm4/t3b", false);
c9 = new Client (authority, "/test/realm4/t3c", false);
+ t3cond1 = new CountDownLatch(1);
c7.start ();
- TestHttpServer.waitForCondition ("T3cond1");
+ t3cond1.await();
c8.start ();
c9.start ();
c7.join(); c8.join(); c9.join();
int f = auth.getCount();
if (f != 2) {
- except ("Authenticator was called "+f+" times. Should be: " + 2);
+ except ("Authenticator was called "+f+" times. Should be: " + 2,
+ server);
}
if (error) {
- except ("error occurred");
+ except ("error occurred", server);
}
}
public static void main (String[] args) throws Exception {
+ new B4769350().runTest(args[0].equals ("proxy"));
+ }
+
+ public void runTest(boolean proxy) throws Exception {
System.setProperty ("http.maxRedirects", Integer.toString (redirects));
System.setProperty ("http.auth.serializeRequests", "true");
Authenticator.setDefault (auth);
- boolean proxy = args[0].equals ("proxy");
- try {
- server = new TestHttpServer (new CallBack(), 10, 1, 0);
- System.out.println ("Server: listening on port: " + server.getLocalPort());
+ try (Server server = new Server()) {
+ server.startServer();
+ System.out.println ("Server: listening on port: "
+ + server.getPort());
if (proxy) {
System.setProperty ("http.proxyHost", "localhost");
- System.setProperty ("http.proxyPort",Integer.toString(server.getLocalPort()));
- doProxyTests ("www.foo.com");
+ System.setProperty ("http.proxyPort",
+ Integer.toString(server.getPort()));
+ doProxyTests ("www.foo.com", server);
} else {
- doServerTests ("localhost:"+server.getLocalPort());
+ doServerTests ("localhost:"+server.getPort(), server);
}
- server.terminate();
-
- } catch (Exception e) {
- if (server != null) {
- server.terminate();
- }
- throw e;
}
+
}
- static void pause (int millis) {
- try {
- Thread.sleep (millis);
- } catch (InterruptedException e) {}
- }
-
- public static void except (String s) {
- server.terminate();
+ public static void except (String s, Server server) {
+ server.close();
throw new RuntimeException (s);
}
@@ -368,13 +498,10 @@
super ();
}
- int count = 0;
+ volatile int count = 0;
+ @Override
public PasswordAuthentication getPasswordAuthentication () {
- //System.out.println ("Authenticator called: " + getRequestingPrompt());
- //try {
- //Thread.sleep (1000);
- //} catch (InterruptedException e) {}
PasswordAuthentication pw;
pw = new PasswordAuthentication ("user", "pass1".toCharArray());
count ++;
@@ -386,7 +513,8 @@
}
public int getCount () {
- return (count);
+ return count;
}
}
}
+
diff --git a/test/java/net/CookieHandler/TestHttpCookie.java b/test/java/net/CookieHandler/TestHttpCookie.java
index 55037a0..2a6526f 100644
--- a/test/java/net/CookieHandler/TestHttpCookie.java
+++ b/test/java/net/CookieHandler/TestHttpCookie.java
@@ -24,7 +24,7 @@
/**
* @test
* @summary Unit test for java.net.HttpCookie
- * @bug 6244040 6277796 6277801 6277808 6294071 6692802 6790677 6901170
+ * @bug 6244040 6277796 6277801 6277808 6294071 6692802 6790677 6901170 8020758
* @author Edward Wang
*/
@@ -381,6 +381,9 @@
// CR 6692802: HttpOnly flag
test("set-cookie: CUSTOMER=WILE_E_COYOTE;HttpOnly").httpOnly(true);
test("set-cookie: CUSTOMER=WILE_E_COYOTE").httpOnly(false);
+
+ // space disallowed in name (both Netscape and RFC2965)
+ test("set-cookie: CUST OMER=WILE_E_COYOTE").nil();
}
static void header(String prompt) {
diff --git a/test/java/net/NetworkInterface/MemLeakTest.java b/test/java/net/NetworkInterface/MemLeakTest.java
deleted file mode 100644
index 11791ae..0000000
--- a/test/java/net/NetworkInterface/MemLeakTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * 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 8022584
- * @summary Some NetworkInterface methods can leak native memory
- * @run main/othervm/timeout=700 MemLeakTest
- */
-
-/* Note: the test can cause a memory leak that's why othervm option is required
- */
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Collection;
-import java.util.Collections;
-
-public class MemLeakTest {
-
- /**
- * Memory leak is assumed, if application consumes more than specified amount of memory during its execution.
- * The number is given in Kb.
- */
- private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb
-
- public static void main(String[] args)
- throws Exception {
-
- if (!System.getProperty("os.name").equals("Linux")) {
- System.out.println("Test only runs on Linux");
- return;
- }
-
- // warm up
- accessNetInterfaces(3);
-
- long vMemBefore = getVMemSize();
- accessNetInterfaces(500_000);
- long vMemAfter = getVMemSize();
-
- long vMemDelta = vMemAfter - vMemBefore;
- if (vMemDelta > MEM_LEAK_THRESHOLD) {
- throw new Exception("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(greater than " + MEM_LEAK_THRESHOLD + "Kb)");
- }
-
- System.out.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " +
- "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)");
- }
-
- private static void accessNetInterfaces(int times) {
- try {
- Collection<NetworkInterface> interfaces =
- Collections.list(NetworkInterface.getNetworkInterfaces());
- for (int i = 0; i != times; ++i) {
- for (NetworkInterface netInterface : interfaces) {
- netInterface.getMTU();
- netInterface.isLoopback();
- netInterface.isUp();
- netInterface.isPointToPoint();
- netInterface.supportsMulticast();
- }
- }
- } catch (SocketException ignore) {}
- }
-
- /**
- * Returns size of virtual memory allocated to the process in Kb.
- * Linux specific. On other platforms and in case of any errors returns 0.
- */
- private static long getVMemSize() {
-
- // Refer to the Linux proc(5) man page for details about /proc/self/stat file
- //
- // In short, this file contains status information about the current process
- // written in one line. The fields are separated with spaces.
- // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes'
-
- try (FileReader fileReader = new FileReader("/proc/self/stat");
- BufferedReader bufferedReader = new BufferedReader(fileReader)) {
- String line = bufferedReader.readLine();
- return Long.parseLong(line.split(" ")[22]) / 1024;
- } catch (Exception ignore) {}
- return 0;
- }
-}
diff --git a/test/java/net/ProxySelector/SystemProxies.java b/test/java/net/ProxySelector/SystemProxies.java
index d02d698..a6ca574 100644
--- a/test/java/net/ProxySelector/SystemProxies.java
+++ b/test/java/net/ProxySelector/SystemProxies.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -33,29 +33,39 @@
public class SystemProxies {
- static final String uriAuthority = "myMachine/";
+ static final String[] uriAuthority = { "myMachine/", "local", "localhost",
+ "127.0.0.1", "127.0.0.123",
+ "127.0.2.2", "127.3.3.3",
+ "128.0.0.1" };
static final ProxySelector proxySel = ProxySelector.getDefault();
public static void main(String[] args) {
if (! "true".equals(System.getProperty("java.net.useSystemProxies"))) {
- System.out.println("Usage: java -Djava.net.useSystemProxies SystemProxies");
+ System.out.println("Usage: java -Djava.net.useSystemProxies=true SystemProxies");
return;
}
printProxies("http://");
printProxies("https://");
printProxies("ftp://");
+ printProxies("none://");
+ printProxies("gopher://");
+ printProxies("rtsp://");
+ printProxies("socket://");
}
static void printProxies(String proto) {
- String uriStr = proto + uriAuthority;
- try {
- List<Proxy> proxies = proxySel.select(new URI(uriStr));
- System.out.println("Proxies returned for " + uriStr);
- for (Proxy proxy : proxies)
- System.out.println("\t" + proxy);
- } catch (URISyntaxException e) {
- System.err.println(e);
+ System.out.println("Protocol:" + proto);
+ for (String uri : uriAuthority) {
+ String uriStr = proto + uri;
+ try {
+ List<Proxy> proxies = proxySel.select(new URI(uriStr));
+ System.out.println("\tProxies returned for " + uriStr);
+ for (Proxy proxy : proxies)
+ System.out.println("\t\t" + proxy);
+ } catch (URISyntaxException e) {
+ System.err.println(e);
+ }
}
}
}
diff --git a/test/java/net/URLClassLoader/NullURLTest.java b/test/java/net/URLClassLoader/NullURLTest.java
new file mode 100644
index 0000000..4171a4f
--- /dev/null
+++ b/test/java/net/URLClassLoader/NullURLTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7179567
+ * @summary Test that URLClassLoader public constructors and factory methods
+ * throw NullPointerException when appropriate.
+ *
+ * Tests whether URLClassLoader public constructors and factory methods throw
+ * appropriate NullPointerExceptions for 1) a null URL array parameter, and
+ * 2) a non-null URL array containing a null element.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.jar.JarFile;
+
+public class NullURLTest {
+ JarFile jarFile;
+
+ public static void main(String[] args) throws Throwable {
+ new NullURLTest();
+ }
+
+ NullURLTest() throws Throwable {
+ File local = new File(System.getProperty("test.src", "."), "jars");
+ String path = "jar:file:"
+ + local.getPath()
+ + "/class_path_test.jar!/Foo.class";
+
+ URL validURL = new URL(path);
+ URL[] validURLArray = new URL[] { validURL, validURL };
+ URL[] invalidURLArray = new URL[] { validURL, null };
+
+ int failures = 0;
+ URLClassLoader loader;
+
+ try {
+ loader = new URLClassLoader(validURLArray);
+ } catch (Throwable t) {
+ System.err.println("URLClassLoader(validURLArray) threw " + t);
+ failures++;
+ }
+ try {
+ loader = new URLClassLoader(null);
+ System.err.println("URLClassLoader(null) did not throw NPE");
+ failures++;
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // This section should be uncommented if 8026517 is fixed.
+// try {
+// loader = new URLClassLoader(invalidURLArray);
+// System.err.println("URLClassLoader(invalidURLArray) did not throw NPE");
+// failures++;
+// } catch (NullPointerException e) {
+// // expected
+// }
+
+ try {
+ loader = new URLClassLoader(validURLArray, null);
+ } catch (Throwable t) {
+ System.err.println("URLClassLoader(validURLArray, null) threw " + t);
+ failures++;
+ }
+ try {
+ loader = new URLClassLoader(null, null);
+ System.err.println("URLClassLoader(null, null) did not throw NPE");
+ failures++;
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // This section should be uncommented if 8026517 is fixed.
+// try {
+// loader = new URLClassLoader(invalidURLArray, null);
+// System.err.println("URLClassLoader(invalidURLArray, null) did not throw NPE");
+// failures++;
+// } catch (NullPointerException e) {
+// // expected
+// }
+
+ try {
+ loader = new URLClassLoader(validURLArray, null, null);
+ } catch (Throwable t) {
+ System.err.println("URLClassLoader(validURLArray, null, null) threw " + t);
+ failures++;
+ }
+ try {
+ loader = new URLClassLoader(null, null, null);
+ System.err.println("URLClassLoader(null, null, null) did not throw NPE");
+ failures++;
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // This section should be uncommented if 8026517 is fixed.
+// try {
+// loader = new URLClassLoader(invalidURLArray, null, null);
+// System.err.println("URLClassLoader(invalidURLArray, null, null) did not throw NPE");
+// failures++;
+// } catch (NullPointerException e) {
+// // expected
+// }
+
+ try {
+ loader = URLClassLoader.newInstance(validURLArray);
+ } catch (Throwable t) {
+ System.err.println("URLClassLoader.newInstance(validURLArray) threw " + t);
+ failures++;
+ }
+ try {
+ loader = URLClassLoader.newInstance(null);
+ System.err.println("URLClassLoader.newInstance(null) did not throw NPE");
+ failures++;
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // This section should be uncommented if 8026517 is fixed.
+// try {
+// loader = URLClassLoader.newInstance(invalidURLArray);
+// System.err.println("URLClassLoader.newInstance(invalidURLArray) did not throw NPE");
+// failures++;
+// } catch (NullPointerException e) {
+// // expected
+// }
+
+ try {
+ loader = URLClassLoader.newInstance(validURLArray, null);
+ } catch (Throwable t) {
+ System.err.println("URLClassLoader.newInstance(validURLArray, null) threw " + t);
+ failures++;
+ }
+ try {
+ loader = URLClassLoader.newInstance(null, null);
+ System.err.println("URLClassLoader.newInstance(null, null) did not throw NPE");
+ failures++;
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // This section should be uncommented if 8026517 is fixed.
+// try {
+// loader = URLClassLoader.newInstance(invalidURLArray, null);
+// System.err.println("URLClassLoader.newInstance(invalidURLArray, null) did not throw NPE");
+// failures++;
+// } catch (NullPointerException e) {
+// // expected
+// }
+
+ if (failures != 0) {
+ throw new Exception("URLClassLoader NullURLTest had "+failures+" failures!");
+ }
+ }
+}
diff --git a/test/java/net/URLPermission/URLPermissionTest.java b/test/java/net/URLPermission/URLPermissionTest.java
index 07299b2..3bf862b 100644
--- a/test/java/net/URLPermission/URLPermissionTest.java
+++ b/test/java/net/URLPermission/URLPermissionTest.java
@@ -26,7 +26,7 @@
/**
* @test
- * @bug 8010464
+ * @bug 8010464 8027570
*/
public class URLPermissionTest {
@@ -110,6 +110,28 @@
return new ActionImpliesTest(arg1, arg2, expected);
}
+ static class HashCodeTest extends Test {
+ String arg1, arg2;
+ int hash;
+
+ HashCodeTest(String arg1, String arg2, int hash) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.hash = hash;
+ }
+
+ @Override
+ boolean execute() {
+ URLPermission p = new URLPermission(arg1, arg2);
+ int h = p.hashCode();
+ return h == hash;
+ }
+ }
+
+ static HashCodeTest hashtest(String arg1, String arg2, int expected) {
+ return new HashCodeTest(arg1, arg2, expected);
+ }
+
static class URLEqualityTest extends Test {
String arg1, arg2;
@@ -178,6 +200,11 @@
extest("http:")
};
+ static Test[] hashTests = {
+ hashtest("http://www.foo.com/path", "GET:X-Foo", 388644203),
+ hashtest("http:*", "*:*", 3255810)
+ };
+
static Test[] pathImplies2 = {
imtest("http://[FE80::]:99", "http://[fe80:0::]:99", true),
@@ -326,6 +353,17 @@
}
+ for (int i=0; i<hashTests.length; i++) {
+ HashCodeTest test = (HashCodeTest)hashTests[i];
+ boolean result = test.execute();
+ if (!result) {
+ System.out.printf ("test failed: %s %s %d\n", test.arg1, test.arg2, test.hash);
+ failed = true;
+ } else {
+ System.out.println ("hash test " + i + " OK");
+ }
+ }
+
for (int i=0; i<exceptionTests.length; i++) {
ExTest test = (ExTest)exceptionTests[i];
boolean result = test.execute();
diff --git a/test/java/net/URLPermission/nstest/LookupTest.java b/test/java/net/URLPermission/nstest/LookupTest.java
new file mode 100644
index 0000000..5b76357
--- /dev/null
+++ b/test/java/net/URLPermission/nstest/LookupTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * SimpleNameServiceDescriptor.java
+ * @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun LookupTest
+ */
+
+/**
+ * This is a simple smoke test of the HttpURLPermission mechanism, which
+ * checks for either IOException (due to unknown host) or SecurityException
+ * due to lack of permission to connect
+ */
+
+import java.net.*;
+import java.io.*;
+
+public class LookupTest {
+
+ static void test(
+ String url, boolean throwsSecException, boolean throwsIOException)
+ {
+ try {
+ URL u = new URL(url);
+ System.err.println ("Connecting to " + u);
+ URLConnection urlc = u.openConnection();
+ InputStream is = urlc.getInputStream();
+ } catch (SecurityException e) {
+ if (!throwsSecException) {
+ throw new RuntimeException ("(1) was not expecting " + e);
+ }
+ return;
+ } catch (IOException ioe) {
+ if (!throwsIOException) {
+ throw new RuntimeException ("(2) was not expecting " + ioe);
+ }
+ return;
+ }
+ if (throwsSecException || throwsIOException) {
+ System.err.printf ("was expecting a %s\n", throwsSecException ?
+ "security exception" : "IOException");
+ throw new RuntimeException("was expecting an exception");
+ }
+ }
+
+ public static void main(String args[]) throws Exception {
+ SimpleNameService.put("allowedAndFound.com", "127.0.0.1");
+ SimpleNameService.put("notAllowedButFound.com", "99.99.99.99");
+ // name "notAllowedAndNotFound.com" is not in map
+ // name "allowedButNotfound.com" is not in map
+ startServer();
+
+ String policyFileName = "file://" + System.getProperty("test.src", ".") + "/policy";
+ System.err.println ("policy = " + policyFileName);
+
+ System.setProperty("java.security.policy", policyFileName);
+
+ System.setSecurityManager(new SecurityManager());
+
+ test("http://allowedAndFound.com:50100/foo", false, false);
+
+ test("http://notAllowedButFound.com:50100/foo", true, false);
+
+ test("http://allowedButNotfound.com:50100/foo", false, true);
+
+ test("http://notAllowedAndNotFound.com:50100/foo", true, false);
+ }
+
+ static Thread server;
+ static ServerSocket serverSocket;
+
+ static class Server extends Thread {
+ public void run() {
+ byte[] buf = new byte[1000];
+ try {
+ while (true) {
+ Socket s = serverSocket.accept();
+ InputStream i = s.getInputStream();
+ i.read(buf);
+ OutputStream o = s.getOutputStream();
+ String rsp = "HTTP/1.1 200 Ok\r\n" +
+ "Connection: close\r\nContent-length: 0\r\n\r\n";
+ o.write(rsp.getBytes());
+ o.close();
+ }
+ } catch (IOException e) {
+ return;
+ }
+ }
+ }
+
+ static void startServer() {
+ try {
+ serverSocket = new ServerSocket(50100);
+ server = new Server();
+ server.start();
+ } catch (Exception e) {
+ throw new RuntimeException ("Test failed to initialize");
+ }
+ }
+}
diff --git a/test/java/net/URLPermission/nstest/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/test/java/net/URLPermission/nstest/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..b7527c0
--- /dev/null
+++ b/test/java/net/URLPermission/nstest/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1,22 @@
+# Copyright (c) 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.
+#
+# 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.
+
+SimpleNameServiceDescriptor # name service provider descriptor
diff --git a/test/java/net/URLPermission/nstest/SimpleNameService.java b/test/java/net/URLPermission/nstest/SimpleNameService.java
new file mode 100644
index 0000000..9d58455
--- /dev/null
+++ b/test/java/net/URLPermission/nstest/SimpleNameService.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * 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.
+ */
+
+/*
+ * A simple name service based on an in-memory HashMap.
+ */
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import sun.net.spi.nameservice.*;
+import java.util.*;
+
+public final class SimpleNameService implements NameService {
+
+ private static LinkedHashMap hosts = new LinkedHashMap();
+
+ private static String addrToString(byte addr[]) {
+ return Byte.toString(addr[0]) + "." +
+ Byte.toString(addr[1]) + "." +
+ Byte.toString(addr[2]) + "." +
+ Byte.toString(addr[3]);
+ }
+
+ // ------------
+
+ public static void put(String host, String addr) {
+ hosts.put(host, addr);
+ }
+
+ public static void put(String host, byte addr[]) {
+ hosts.put(host, addrToString(addr));
+ }
+
+ public static void remove(String host) {
+ hosts.remove(host);
+ }
+
+ public static int entries () {
+ return hosts.size();
+ }
+
+ public static int lookupCalls() {
+ return lookupCalls;
+ }
+
+ static int lookupCalls = 0;
+
+ // ------------
+
+ public SimpleNameService() throws Exception {
+ }
+
+ public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
+
+ lookupCalls ++;
+
+ String value = (String)hosts.get(host);
+ if (value == null) {
+ throw new UnknownHostException(host);
+ }
+ StringTokenizer st = new StringTokenizer(value, ".");
+ byte addr[] = new byte[4];
+ for (int i=0; i<4; i++) {
+ addr[i] = (byte)Integer.parseInt(st.nextToken());
+ }
+ InetAddress[] res = new InetAddress[1];
+ res[0] = InetAddress.getByAddress(host, addr);
+ return res;
+ }
+
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ String addrString = addrToString(addr);
+ Iterator i = hosts.keySet().iterator();
+ while (i.hasNext()) {
+ String host = (String)i.next();
+ String value = (String)hosts.get(host);
+ if (value.equals(addrString)) {
+ return host;
+ }
+ }
+ throw new UnknownHostException();
+ }
+}
diff --git a/test/java/net/URLPermission/nstest/SimpleNameServiceDescriptor.java b/test/java/net/URLPermission/nstest/SimpleNameServiceDescriptor.java
new file mode 100644
index 0000000..373d10b
--- /dev/null
+++ b/test/java/net/URLPermission/nstest/SimpleNameServiceDescriptor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * 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.
+ */
+
+/*
+ * Descriptor for the simple name service
+ */
+import sun.net.spi.nameservice.*;
+
+public final class SimpleNameServiceDescriptor implements NameServiceDescriptor {
+ /**
+ * Create a new instance of the corresponding name service.
+ */
+ public NameService createNameService() throws Exception {
+ return new SimpleNameService();
+ }
+
+ /**
+ * Returns this service provider's name
+ *
+ */
+ public String getProviderName() {
+ return "sun";
+ }
+
+ /**
+ * Returns this name service type
+ * "dns" "nis" etc
+ */
+ public String getType() {
+ return "simple";
+ }
+}
diff --git a/test/java/net/URLPermission/nstest/policy b/test/java/net/URLPermission/nstest/policy
new file mode 100644
index 0000000..967af68
--- /dev/null
+++ b/test/java/net/URLPermission/nstest/policy
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 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.
+//
+// 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.
+//
+
+grant {
+ permission java.net.URLPermission "http://allowedAndFound.com:50100/-", "*:*";
+ permission java.net.URLPermission "http://allowedButNotfound.com:50100/-", "*:*";
+
+ // needed for HttpServer
+ permission "java.net.SocketPermission" "localhost:1024-", "resolve,accept";
+};
+
+// Normal permissions that aren't granted when run under jtreg
+
+grant codeBase "file:${{java.ext.dirs}}/*" {
+ permission java.security.AllPermission;
+};
+
+grant codeBase "file:${{java.home}}/jre/lib/rt.jar" {
+ permission java.security.AllPermission;
+};
+
diff --git a/test/java/nio/channels/FileChannel/InterruptMapDeadlock.java b/test/java/nio/channels/FileChannel/InterruptMapDeadlock.java
new file mode 100644
index 0000000..43d0e36
--- /dev/null
+++ b/test/java/nio/channels/FileChannel/InterruptMapDeadlock.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8024833
+ * @summary Tests interruption of threads mapping sections of a file channel in
+ * an attempt to deadlock due to nesting of begin calls.
+ */
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.*;
+import java.util.concurrent.Semaphore;
+import static java.nio.file.StandardOpenOption.*;
+
+public class InterruptMapDeadlock {
+
+ static class Mapper extends Thread {
+ final FileChannel fc;
+ final Semaphore gate;
+ volatile Exception exception;
+
+ Mapper(FileChannel fc, Semaphore gate) {
+ this.fc = fc;
+ this.gate = gate;
+ }
+
+ @Override
+ public void run() {
+ try {
+ gate.acquireUninterruptibly();
+ fc.map(MapMode.READ_ONLY, 0, 1);
+ throw new Exception("Map succeeded");
+ } catch (IOException x) {
+ System.out.println(x.getClass() + " (expected)");
+ } catch (Exception unexpected) {
+ this.exception = unexpected;
+ }
+ }
+
+ Exception exception() {
+ return exception;
+ }
+
+ static Mapper startMapper(FileChannel fc, Semaphore gate) {
+ Mapper r = new Mapper(fc, gate);
+ r.setDaemon(true);
+ r.start();
+ return r;
+ }
+ }
+
+ static class Interruptor extends Thread {
+
+ final Mapper[] mappers;
+ final Semaphore gate;
+
+ Interruptor(Mapper[] mappers, Semaphore gate) {
+ this.mappers = mappers;
+ this.gate = gate;
+ }
+
+ public void run() {
+ gate.release(mappers.length);
+ for (Mapper m : mappers) {
+ m.interrupt();
+ }
+ }
+ }
+ // the number of mapper threads to start
+ private static final int MAPPER_COUNT = 4;
+
+ public static void main(String[] args) throws Exception {
+ Path file = Paths.get("data.txt");
+ FileChannel.open(file, CREATE, TRUNCATE_EXISTING, WRITE).close();
+
+ Mapper[] mappers = new Mapper[MAPPER_COUNT];
+
+ for (int i=1; i<=20; i++) {
+ System.out.format("Iteration: %s%n", i);
+
+ FileChannel fc = FileChannel.open(file);
+ boolean failed = false;
+
+ Semaphore gate = new Semaphore(0);
+ // start mapper threads
+ for (int j=0; j<MAPPER_COUNT; j++) {
+ mappers[j] = Mapper.startMapper(fc, gate);
+ }
+
+ // interrupt and wait for the mappers to terminate
+ Interruptor interruptor = new Interruptor(mappers, gate);
+ interruptor.start();
+ try {
+ interruptor.join(10000);
+ if (interruptor.isAlive()) {
+ System.err.println("Interruptor thread did not terminate:");
+ Throwable t = new Exception("Stack trace");
+ t.setStackTrace(interruptor.getStackTrace());
+ t.printStackTrace();
+ failed = true;
+ }
+ } catch (InterruptedException x) {
+ System.err.println("Main thread was interrupted");
+ failed = true;
+ }
+
+ for (Mapper m: mappers) {
+ try {
+ m.join(10000);
+ Exception e = m.exception();
+ if (e != null) {
+ System.err.println("Mapper thread failed with: " + e);
+ failed = true;
+ } else if (m.isAlive()) {
+ System.err.println("Mapper thread did not terminate:");
+ Throwable t = new Exception("Stack trace");
+ t.setStackTrace(m.getStackTrace());
+ t.printStackTrace();
+ failed = true;
+ }
+ } catch (InterruptedException x) {
+ System.err.println("Main thread was interrupted");
+ failed = true;
+ }
+ }
+
+ if (failed)
+ throw new RuntimeException("Test failed - see log for details");
+ else
+ fc.close();
+ }
+ }
+}
diff --git a/test/java/nio/channels/SocketChannel/ShortWrite.java b/test/java/nio/channels/SocketChannel/ShortWrite.java
index 2f324c3..198bfc3 100644
--- a/test/java/nio/channels/SocketChannel/ShortWrite.java
+++ b/test/java/nio/channels/SocketChannel/ShortWrite.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 7176630
+ * @bug 7176630 7074436
* @summary Check for short writes on SocketChannels configured in blocking mode
*/
@@ -38,11 +38,12 @@
static final Random rand = new Random();
/**
- * Returns a checksum on the remaining bytes in the given buffer.
+ * Returns a checksum on the remaining bytes in the given buffers.
*/
- static long computeChecksum(ByteBuffer bb) {
+ static long computeChecksum(ByteBuffer... bufs) {
CRC32 crc32 = new CRC32();
- crc32.update(bb);
+ for (int i=0; i<bufs.length; i++)
+ crc32.update(bufs[i]);
return crc32.getValue();
}
@@ -71,15 +72,15 @@
}
/**
- * Run test with a write of the given number of bytes.
+ * Exercise write(ByteBuffer) with given number of bytes.
*/
- static void test(ExecutorService pool,
- SocketChannel source,
- SocketChannel sink,
- int size)
+ static void test1(ExecutorService pool,
+ SocketChannel source,
+ SocketChannel sink,
+ int size)
throws Exception
{
- System.out.println(size);
+ System.out.println("write(ByteBuffer), size=" + size);
// random bytes in the buffer
ByteBuffer buf = ByteBuffer.allocate(size);
@@ -101,6 +102,47 @@
throw new RuntimeException("Checksum did not match");
}
+ /**
+ * Exercise write(ByteBuffer[]) with buffers of the given sizes.
+ */
+ static void testN(ExecutorService pool,
+ SocketChannel source,
+ SocketChannel sink,
+ int... sizes)
+ throws Exception
+ {
+ System.out.print("write(ByteBuffer[]), sizes=");
+ for (int size: sizes)
+ System.out.print(size + " ");
+ System.out.println();
+
+ int total = 0;
+ int len = sizes.length;
+ ByteBuffer[] bufs = new ByteBuffer[len];
+ for (int i=0; i<len; i++) {
+ int size = sizes[i];
+ ByteBuffer buf = ByteBuffer.allocate(size);
+ rand.nextBytes(buf.array());
+ bufs[i] = buf;
+ total += size;
+ }
+
+ // submit task to read the bytes
+ Future<Long> result = pool.submit(new Reader(sink, total));
+
+ // write the bytes
+ long n = source.write(bufs);
+ if (n != total)
+ throw new RuntimeException("Short write detected");
+
+ // check the bytes that were received match
+ for (int i=0; i<len; i++)
+ bufs[i].rewind();
+ long expected = computeChecksum(bufs);
+ long actual = result.get();
+ if (actual != expected)
+ throw new RuntimeException("Checksum did not match");
+ }
public static void main(String[] args) throws Exception {
ExecutorService pool = Executors.newSingleThreadExecutor();
@@ -114,17 +156,47 @@
try (SocketChannel source = SocketChannel.open(sa);
SocketChannel sink = ssc.accept())
{
- // run tests on sizes around 128k as that is the problem
- // area on Windows.
+ // Exercise write(BufferBuffer) on sizes around 128k
int BOUNDARY = 128 * 1024;
for (int size=(BOUNDARY-2); size<=(BOUNDARY+2); size++) {
- test(pool, source, sink, size);
+ test1(pool, source, sink, size);
}
- // run tests on random sizes
+ // Exercise write(BufferBuffer) on random sizes
for (int i=0; i<20; i++) {
int size = rand.nextInt(1024*1024);
- test(pool, source, sink, size);
+ test1(pool, source, sink, size);
+ }
+
+ // Exercise write(BufferBuffer[]) on sizes around 128k
+ for (int i=BOUNDARY-2; i<=BOUNDARY+2; i++) {
+ testN(pool, source, sink, i);
+ testN(pool, source, sink, 0, i);
+ testN(pool, source, sink, i, 0);
+ for (int j=BOUNDARY-2; j<=BOUNDARY+2; j++) {
+ testN(pool, source, sink, i, j);
+ testN(pool, source, sink, 0, i, j);
+ testN(pool, source, sink, i, 0, j);
+ testN(pool, source, sink, i, j, 0);
+ for (int k=BOUNDARY-2; k<=BOUNDARY+2; k++) {
+ testN(pool, source, sink, i, j, k);
+ testN(pool, source, sink, 0, i, j, k);
+ testN(pool, source, sink, i, 0, j, k);
+ testN(pool, source, sink, i, j, 0, k);
+ testN(pool, source, sink, i, j, k, 0);
+ }
+ }
+ }
+
+ // Exercise write(BufferBuffer[]) on random sizes
+ // (assumes IOV_MAX >= 8)
+ for (int i=0; i<20; i++) {
+ int n = rand.nextInt(9);
+ int[] sizes = new int[n];
+ for (int j=0; j<n; j++) {
+ sizes[j] = rand.nextInt(1024*1024);
+ }
+ testN(pool, source, sink, sizes);
}
}
}
diff --git a/test/java/nio/file/Files/StreamTest.java b/test/java/nio/file/Files/StreamTest.java
index 839b11f..0259fac 100644
--- a/test/java/nio/file/Files/StreamTest.java
+++ b/test/java/nio/file/Files/StreamTest.java
@@ -23,6 +23,7 @@
/* @test
* @bug 8006884 8019526
+ * @library ..
* @build PassThroughFileSystem FaultyFileSystem
* @run testng StreamTest
* @summary Unit test for java.nio.file.Files methods that return a Stream
diff --git a/test/java/security/Signature/SignatureGetAlgorithm.java b/test/java/security/Signature/SignatureGetAlgorithm.java
index 2111ffc..6732d66 100644
--- a/test/java/security/Signature/SignatureGetAlgorithm.java
+++ b/test/java/security/Signature/SignatureGetAlgorithm.java
@@ -49,7 +49,7 @@
public static class TestProvider extends Provider {
TestProvider() {
- super("test", 1.0, "test");
+ super("testSignatureGetAlgorithm", 1.0, "test Signatures");
put("Signature.MySignatureAlg",
"SignatureGetAlgorithm$MySignatureAlg");
}
diff --git a/test/java/security/cert/PKIXRevocationChecker/UnitTest.java b/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
index 5c5f5bc..8ddfda2 100644
--- a/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
+++ b/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6854712 7171570 8010748
+ * @bug 6854712 7171570 8010748 8025287
* @summary Basic unit test for PKIXRevocationChecker
*/
@@ -44,6 +44,8 @@
CertPathChecker cpc = cpv.getRevocationChecker();
PKIXRevocationChecker prc = (PKIXRevocationChecker)cpc;
+ prc.init(false);
+
System.out.println("Testing that get methods return null or " +
"empty lists/sets/maps");
requireNull(prc.getOcspResponder(), "getOcspResponder()");
diff --git a/test/java/time/tck/java/time/TCKZoneId.java b/test/java/time/tck/java/time/TCKZoneId.java
index c036dee..a90c9ab 100644
--- a/test/java/time/tck/java/time/TCKZoneId.java
+++ b/test/java/time/tck/java/time/TCKZoneId.java
@@ -94,47 +94,6 @@
public class TCKZoneId extends AbstractTCKTest {
//-----------------------------------------------------------------------
- // OLD_SHORT_IDS
- //-----------------------------------------------------------------------
- public void test_constant_OLD_IDS_PRE_2005() {
- Map<String, String> ids = ZoneId.OLD_SHORT_IDS;
- assertEquals(ids.get("EST"), "America/New_York");
- assertEquals(ids.get("MST"), "America/Denver");
- assertEquals(ids.get("HST"), "Pacific/Honolulu");
- assertEquals(ids.get("ACT"), "Australia/Darwin");
- assertEquals(ids.get("AET"), "Australia/Sydney");
- assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires");
- assertEquals(ids.get("ART"), "Africa/Cairo");
- assertEquals(ids.get("AST"), "America/Anchorage");
- assertEquals(ids.get("BET"), "America/Sao_Paulo");
- assertEquals(ids.get("BST"), "Asia/Dhaka");
- assertEquals(ids.get("CAT"), "Africa/Harare");
- assertEquals(ids.get("CNT"), "America/St_Johns");
- assertEquals(ids.get("CST"), "America/Chicago");
- assertEquals(ids.get("CTT"), "Asia/Shanghai");
- assertEquals(ids.get("EAT"), "Africa/Addis_Ababa");
- assertEquals(ids.get("ECT"), "Europe/Paris");
- assertEquals(ids.get("IET"), "America/Indiana/Indianapolis");
- assertEquals(ids.get("IST"), "Asia/Kolkata");
- assertEquals(ids.get("JST"), "Asia/Tokyo");
- assertEquals(ids.get("MIT"), "Pacific/Apia");
- assertEquals(ids.get("NET"), "Asia/Yerevan");
- assertEquals(ids.get("NST"), "Pacific/Auckland");
- assertEquals(ids.get("PLT"), "Asia/Karachi");
- assertEquals(ids.get("PNT"), "America/Phoenix");
- assertEquals(ids.get("PRT"), "America/Puerto_Rico");
- assertEquals(ids.get("PST"), "America/Los_Angeles");
- assertEquals(ids.get("SST"), "Pacific/Guadalcanal");
- assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh");
- }
-
- @Test(expectedExceptions=UnsupportedOperationException.class)
- public void test_constant_OLD_IDS_PRE_2005_immutable() {
- Map<String, String> ids = ZoneId.OLD_SHORT_IDS;
- ids.clear();
- }
-
- //-----------------------------------------------------------------------
// SHORT_IDS
//-----------------------------------------------------------------------
public void test_constant_OLD_IDS_POST_2005() {
diff --git a/test/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java b/test/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java
index 371014f..f2ff1af 100644
--- a/test/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java
+++ b/test/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java
@@ -59,9 +59,6 @@
*/
package tck.java.time.serial;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import tck.java.time.AbstractTCKTest;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
@@ -69,6 +66,10 @@
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import tck.java.time.AbstractTCKTest;
+
/**
* Test OffsetDateTime serialization.
*/
@@ -96,11 +97,6 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos) ) {
dos.writeByte(10); // java.time.Ser.OFFSET_DATE_TIME_TYPE
- }
- byte[] bytes = baos.toByteArray();
- ByteArrayOutputStream baosDateTime = new ByteArrayOutputStream();
- try (DataOutputStream dos = new DataOutputStream(baosDateTime) ) {
- dos.writeByte(5);
dos.writeInt(2012);
dos.writeByte(9);
dos.writeByte(16);
@@ -108,17 +104,11 @@
dos.writeByte(17);
dos.writeByte(59);
dos.writeInt(464_000_000);
- }
- byte[] bytesDateTime = baosDateTime.toByteArray();
- ByteArrayOutputStream baosOffset = new ByteArrayOutputStream();
- try (DataOutputStream dos = new DataOutputStream(baosOffset) ) {
- dos.writeByte(8);
dos.writeByte(4); // quarter hours stored: 3600 / 900
}
- byte[] bytesOffset = baosOffset.toByteArray();
+ byte[] bytes = baos.toByteArray();
LocalDateTime ldt = LocalDateTime.of(2012, 9, 16, 22, 17, 59, 464_000_000);
- assertSerializedBySer(OffsetDateTime.of(ldt, ZoneOffset.ofHours(1)), bytes, bytesDateTime, bytesOffset);
+ assertSerializedBySer(OffsetDateTime.of(ldt, ZoneOffset.ofHours(1)), bytes);
}
-
}
diff --git a/test/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java b/test/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java
index ee04e1e..292ef82 100644
--- a/test/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java
+++ b/test/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java
@@ -97,25 +97,14 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos) ) {
dos.writeByte(9); // java.time.Ser.OFFSET_TIME_TYPE
- }
- byte[] bytes = baos.toByteArray();
- ByteArrayOutputStream baosTime = new ByteArrayOutputStream();
- try (DataOutputStream dos = new DataOutputStream(baosTime) ) {
- dos.writeByte(4);
dos.writeByte(22);
dos.writeByte(17);
dos.writeByte(59);
dos.writeInt(464_000_000);
- }
- byte[] bytesTime = baosTime.toByteArray();
- ByteArrayOutputStream baosOffset = new ByteArrayOutputStream();
- try (DataOutputStream dos = new DataOutputStream(baosOffset) ) {
- dos.writeByte(8);
dos.writeByte(4); // quarter hours stored: 3600 / 900
}
- byte[] bytesOffset = baosOffset.toByteArray();
- assertSerializedBySer(OffsetTime.of(22, 17, 59, 464_000_000, ZoneOffset.ofHours(1)), bytes,
- bytesTime, bytesOffset);
+ byte[] bytes = baos.toByteArray();
+ assertSerializedBySer(OffsetTime.of(22, 17, 59, 464_000_000, ZoneOffset.ofHours(1)), bytes);
}
diff --git a/test/java/time/test/java/time/format/TestReducedParser.java b/test/java/time/test/java/time/format/TestReducedParser.java
index ae4ff98..e9df91f 100644
--- a/test/java/time/test/java/time/format/TestReducedParser.java
+++ b/test/java/time/test/java/time/format/TestReducedParser.java
@@ -78,10 +78,12 @@
import java.time.chrono.JapaneseChronology;
import java.time.chrono.MinguoChronology;
import java.time.chrono.ThaiBuddhistChronology;
+import java.time.chrono.ThaiBuddhistDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
+import java.time.temporal.TemporalQueries;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -443,6 +445,52 @@
}
+ @Test
+ public void test_reducedWithLateChronoChange() {
+ ThaiBuddhistDate date = ThaiBuddhistDate.of(2543, 1, 1);
+ DateTimeFormatter df
+ = new DateTimeFormatterBuilder()
+ .appendValueReduced(YEAR, 2, 2, LocalDate.of(2000, 1, 1))
+ .appendLiteral(" ")
+ .appendChronologyId()
+ .toFormatter();
+ int expected = date.get(YEAR);
+ String input = df.format(date);
+
+ ParsePosition pos = new ParsePosition(0);
+ TemporalAccessor parsed = df.parseUnresolved(input, pos);
+ assertEquals(pos.getIndex(), input.length(), "Input not parsed completely");
+ assertEquals(pos.getErrorIndex(), -1, "Error index should be -1 (no-error)");
+ int actual = parsed.get(YEAR);
+ assertEquals(actual, expected,
+ String.format("Wrong date parsed, chrono: %s, input: %s",
+ parsed.query(TemporalQueries.chronology()), input));
+
+ }
+
+ @Test
+ public void test_reducedWithLateChronoChangeTwice() {
+ DateTimeFormatter df
+ = new DateTimeFormatterBuilder()
+ .appendValueReduced(YEAR, 2, 2, LocalDate.of(2000, 1, 1))
+ .appendLiteral(" ")
+ .appendChronologyId()
+ .appendLiteral(" ")
+ .appendChronologyId()
+ .toFormatter();
+ int expected = 2044;
+ String input = "44 ThaiBuddhist ISO";
+ ParsePosition pos = new ParsePosition(0);
+ TemporalAccessor parsed = df.parseUnresolved(input, pos);
+ assertEquals(pos.getIndex(), input.length(), "Input not parsed completely: " + pos);
+ assertEquals(pos.getErrorIndex(), -1, "Error index should be -1 (no-error)");
+ int actual = parsed.get(YEAR);
+ assertEquals(actual, expected,
+ String.format("Wrong date parsed, chrono: %s, input: %s",
+ parsed.query(TemporalQueries.chronology()), input));
+
+ }
+
//-----------------------------------------------------------------------
// Class to structure the test data
//-----------------------------------------------------------------------
diff --git a/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
index 6e37235..e16cf7a 100644
--- a/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+++ b/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
@@ -112,13 +112,13 @@
}
private static Set<ZoneId> preferred = new HashSet<>(Arrays.asList(new ZoneId[] {
- ZoneId.of("EST"),
+ ZoneId.of("EST", ZoneId.SHORT_IDS),
ZoneId.of("Asia/Taipei"),
ZoneId.of("CET"),
}));
private static Set<ZoneId> preferred_s = new HashSet<>(Arrays.asList(new ZoneId[] {
- ZoneId.of("EST"),
+ ZoneId.of("EST", ZoneId.SHORT_IDS),
ZoneId.of("CET"),
ZoneId.of("Australia/South"),
ZoneId.of("Australia/West"),
@@ -131,7 +131,7 @@
Object[][] data_preferredZones() {
return new Object[][] {
{"America/New_York", "Eastern Standard Time", none, Locale.ENGLISH, TextStyle.FULL},
- {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL},
+// {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL},
{"Europe/Paris", "Central European Time", none, Locale.ENGLISH, TextStyle.FULL},
{"CET", "Central European Time", preferred, Locale.ENGLISH, TextStyle.FULL},
{"Asia/Shanghai", "China Standard Time", none, Locale.ENGLISH, TextStyle.FULL},
diff --git a/test/java/util/Base64/Base64GetEncoderTest.java b/test/java/util/Base64/Base64GetEncoderTest.java
index c00e2ef..c5658d2 100644
--- a/test/java/util/Base64/Base64GetEncoderTest.java
+++ b/test/java/util/Base64/Base64GetEncoderTest.java
@@ -41,7 +41,7 @@
public class Base64GetEncoderTest {
public static void main(String args[]) throws Throwable {
- final Base64.Encoder encoder = Base64.getEncoder(0, "$$$".getBytes(US_ASCII));
+ final Base64.Encoder encoder = Base64.getMimeEncoder(0, "$$$".getBytes(US_ASCII));
testEncodeToString(encoder);
diff --git a/test/java/util/Base64/TestBase64.java b/test/java/util/Base64/TestBase64.java
index a8895a0..6202356 100644
--- a/test/java/util/Base64/TestBase64.java
+++ b/test/java/util/Base64/TestBase64.java
@@ -23,7 +23,7 @@
/**
* @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 8007379 8008925
- * 8014217
+ * 8014217 8025003
* @summary tests java.util.Base64
*/
@@ -60,13 +60,13 @@
byte[] nl_3 = new byte[] {'\n', '\r', '\n'};
for (int i = 0; i < 10; i++) {
int len = rnd.nextInt(200) + 4;
- test(Base64.getEncoder(len, nl_1),
+ test(Base64.getMimeEncoder(len, nl_1),
Base64.getMimeDecoder(),
numRuns, numBytes);
- test(Base64.getEncoder(len, nl_2),
+ test(Base64.getMimeEncoder(len, nl_2),
Base64.getMimeDecoder(),
numRuns, numBytes);
- test(Base64.getEncoder(len, nl_3),
+ test(Base64.getMimeEncoder(len, nl_3),
Base64.getMimeDecoder(),
numRuns, numBytes);
}
@@ -74,16 +74,16 @@
testNull(Base64.getEncoder());
testNull(Base64.getUrlEncoder());
testNull(Base64.getMimeEncoder());
- testNull(Base64.getEncoder(10, new byte[]{'\n'}));
+ testNull(Base64.getMimeEncoder(10, new byte[]{'\n'}));
testNull(Base64.getDecoder());
testNull(Base64.getUrlDecoder());
testNull(Base64.getMimeDecoder());
- checkNull(new Runnable() { public void run() { Base64.getEncoder(10, null); }});
+ checkNull(new Runnable() { public void run() { Base64.getMimeEncoder(10, null); }});
testIOE(Base64.getEncoder());
testIOE(Base64.getUrlEncoder());
testIOE(Base64.getMimeEncoder());
- testIOE(Base64.getEncoder(10, new byte[]{'\n'}));
+ testIOE(Base64.getMimeEncoder(10, new byte[]{'\n'}));
byte[] src = new byte[1024];
new Random().nextBytes(src);
@@ -93,7 +93,7 @@
testIOE(Base64.getUrlDecoder(), Base64.getUrlEncoder().encode(src));
// illegal line separator
- checkIAE(new Runnable() { public void run() { Base64.getEncoder(10, new byte[]{'\r', 'N'}); }});
+ checkIAE(new Runnable() { public void run() { Base64.getMimeEncoder(10, new byte[]{'\r', 'N'}); }});
// illegal base64 character
decoded[2] = (byte)0xe0;
@@ -109,8 +109,6 @@
Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocateDirect(1024)); }});
// illegal ending unit
- checkIAE(new Runnable() { public void run() { Base64.getMimeDecoder().decode("$=#"); }});
-
checkIOE(new Testable() { public void test() throws IOException {
byte[] bytes = "AA=".getBytes("ASCII");
try (InputStream stream =
@@ -129,6 +127,10 @@
testDecodeUnpadded();
// test mime decoding with ignored character after padding
testDecodeIgnoredAfterPadding();
+
+ // lenient mode for ending unit
+ testLenientPadding();
+
}
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
@@ -436,6 +438,48 @@
}
}
+ private static void testLenientPadding() throws Throwable {
+ String[] data = new String[] {
+ "=", "", // unnecessary padding
+ "QUJD=", "ABC", //"ABC".encode() -> "QUJD"
+
+ "QQ=", "A", // incomplete padding
+ "QQ=N", "A", // incorrect padding
+ "QQ=?", "A",
+ "QUJDQQ=", "ABCA",
+ "QUJDQQ=N", "ABCA",
+ "QUJDQQ=?", "ABCA",
+
+ "QUI=X", "AB", // incorrect padding
+ "QUI=?", "AB", // incorrect padding
+ };
+ Base64.Decoder dec = Base64.getMimeDecoder();
+
+ for (int i = 0; i < data.length; i += 2) {
+ byte[] src = data[i].getBytes("ASCII");
+ byte[] expected = data[i + 1].getBytes("ASCII");
+ // decode(byte[])
+ byte[] ret = dec.decode(src);
+ checkEqual(ret, expected, "lenient padding decoding failed!");
+
+ // decode(String)
+ ret = dec.decode(data[i]);
+ checkEqual(ret, expected, "lenient padding decoding failed!");
+
+ // decode(ByteBuffer)
+ ByteBuffer srcBB = ByteBuffer.wrap(src);
+ ByteBuffer retBB = dec.decode(srcBB);
+ checkEqual(srcBB.remaining(), 0, "lenient padding decoding failed!");
+ checkEqual(Arrays.copyOf(retBB.array(), retBB.remaining()),
+ expected, "lenient padding decoding failed!");
+
+ // wrap.decode(byte[])
+ ret = new byte[10];
+ int n = dec.wrap(new ByteArrayInputStream(src)).read(ret);
+ checkEqual(Arrays.copyOf(ret, n), expected, "lenient padding decoding failed!");
+ }
+ }
+
private static void testDecodeUnpadded() throws Throwable {
byte[] srcA = new byte[] { 'Q', 'Q' };
byte[] srcAA = new byte[] { 'Q', 'Q', 'E'};
diff --git a/test/java/util/Base64/TestBase64Golden.java b/test/java/util/Base64/TestBase64Golden.java
index e99f344..192f2ed 100644
--- a/test/java/util/Base64/TestBase64Golden.java
+++ b/test/java/util/Base64/TestBase64Golden.java
@@ -230,7 +230,7 @@
46, -97, -35, -44, 127, -60, -39, -4, -112, 34, -57, 47, -14, 67,
40, 18, 90, -59, 68, 112, 23, 121, -91, 94, 35, 49, 104, 17, 30,
-80, -104, -3, -53, 27, 38, -72, -47, 113, -52, 18, 5, -126 };
- Encoder encoder = Base64.getEncoder(49, new byte[] { 0x7e });
+ Encoder encoder = Base64.getMimeEncoder(49, new byte[] { 0x7e });
byte[] encoded = encoder.encode(src);
Decoder decoder = Base64.getMimeDecoder();
byte[] decoded = decoder.decode(encoded);
diff --git a/test/java/util/Calendar/JavatimeTest.java b/test/java/util/Calendar/JavatimeTest.java
index 9f61229..6a0a4ff 100644
--- a/test/java/util/Calendar/JavatimeTest.java
+++ b/test/java/util/Calendar/JavatimeTest.java
@@ -114,14 +114,14 @@
zidStr.equals("MST")) {
continue;
}
- ZoneId zid = ZoneId.of(zidStr, ZoneId.OLD_SHORT_IDS);
+ ZoneId zid = ZoneId.of(zidStr, ZoneId.SHORT_IDS);
if (!zid.equals(TimeZone.getTimeZone(zid).toZoneId())) {
throw new RuntimeException("FAILED: zid -> tz -> zid :" + zidStr);
}
TimeZone tz = TimeZone.getTimeZone(zidStr);
// no round-trip for alias and "GMT"
if (!tz.equals(TimeZone.getTimeZone(tz.toZoneId())) &&
- !ZoneId.OLD_SHORT_IDS.containsKey(zidStr) &&
+ !ZoneId.SHORT_IDS.containsKey(zidStr) &&
!zidStr.startsWith("GMT")) {
throw new RuntimeException("FAILED: tz -> zid -> tz :" + zidStr);
}
diff --git a/test/java/util/Map/Defaults.java b/test/java/util/Map/Defaults.java
index f14cd8a..46a49a6 100644
--- a/test/java/util/Map/Defaults.java
+++ b/test/java/util/Map/Defaults.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8010122 8004518 8024331
+ * @bug 8010122 8004518 8024331 8024688
* @summary Test Map default methods
* @author Mike Duigou
* @run testng Defaults
@@ -36,8 +36,8 @@
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
+import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -288,19 +288,11 @@
assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfAbsentNPEHashMap() {
- Object value = new HashMap().computeIfAbsent(KEYS[1], null);
- }
-
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfAbsentNPEHashtable() {
- Object value = new Hashtable().computeIfAbsent(KEYS[1], null);
- }
-
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfAbsentNPETreeMap() {
- Object value = new TreeMap().computeIfAbsent(KEYS[1], null);
+ @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+ public void testComputeIfAbsentNullFunction(String description, Map<IntegerEnum, String> map) {
+ assertThrows( () -> { map.computeIfAbsent(KEYS[1], null);},
+ NullPointerException.class,
+ "Should throw NPE");
}
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
@@ -343,22 +335,14 @@
assertSame(map.get(EXTRA_KEY), null);
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfPresentNPEHashMap() {
- Object value = new HashMap().computeIfPresent(KEYS[1], null);
+ @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+ public void testComputeIfPresentNullFunction(String description, Map<IntegerEnum, String> map) {
+ assertThrows( () -> { map.computeIfPresent(KEYS[1], null);},
+ NullPointerException.class,
+ "Should throw NPE");
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfPresentNPEHashtable() {
- Object value = new Hashtable().computeIfPresent(KEYS[1], null);
- }
-
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeIfPresentNPETreeMap() {
- Object value = new TreeMap().computeIfPresent(KEYS[1], null);
- }
-
- @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+ @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
public void testComputeNulls(String description, Map<IntegerEnum, String> map) {
assertTrue(map.containsKey(null), "null key absent");
assertNull(map.get(null), "value not null");
@@ -444,78 +428,86 @@
assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeNPEHashMap() {
- Object value = new HashMap().compute(KEYS[1], null);
+ @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+ public void testComputeNullFunction(String description, Map<IntegerEnum, String> map) {
+ assertThrows( () -> { map.compute(KEYS[1], null);},
+ NullPointerException.class,
+ "Should throw NPE");
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeNPEHashtable() {
- Object value = new Hashtable().compute(KEYS[1], null);
- }
+ @Test(dataProvider = "MergeCases")
+ private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
+ // add and check initial conditions.
+ switch(oldValue) {
+ case ABSENT :
+ map.remove(EXTRA_KEY);
+ assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
+ break;
+ case NULL :
+ map.put(EXTRA_KEY, null);
+ assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+ assertNull(map.get(EXTRA_KEY), "wrong value");
+ break;
+ case OLDVALUE :
+ map.put(EXTRA_KEY, VALUES[1]);
+ assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+ assertSame(map.get(EXTRA_KEY), VALUES[1], "wrong value");
+ break;
+ default:
+ fail("unexpected old value");
+ }
- @Test(expectedExceptions = {NullPointerException.class})
- public void testComputeNPETreeMap() {
- Object value = new TreeMap().compute(KEYS[1], null);
- }
+ String returned = map.merge(EXTRA_KEY,
+ newValue == Merging.Value.NULL ? (String) null : VALUES[2],
+ merger
+ );
- @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
- public void testMergeNulls(String description, Map<IntegerEnum, String> map) {
- assertTrue(map.containsKey(null), "null key absent");
- assertNull(map.get(null), "value not null");
- assertSame(map.merge(null, EXTRA_VALUE, (v, vv) -> {
- assertNull(v);
- assertSame(vv, EXTRA_VALUE);
- return vv;
- }), EXTRA_VALUE, description);
- assertTrue(map.containsKey(null));
- assertSame(map.get(null), EXTRA_VALUE, description);
+ // check result
+
+ switch(result) {
+ case NULL :
+ assertNull(returned, "wrong value");
+ break;
+ case NEWVALUE :
+ assertSame(returned, VALUES[2], "wrong value");
+ break;
+ case RESULT :
+ assertSame(returned, VALUES[3], "wrong value");
+ break;
+ default:
+ fail("unexpected new value");
+ }
+
+ // check map
+ switch(put) {
+ case ABSENT :
+ assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
+ break;
+ case NULL :
+ assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+ assertNull(map.get(EXTRA_KEY), "wrong value");
+ break;
+ case NEWVALUE :
+ assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+ assertSame(map.get(EXTRA_KEY), VALUES[2], "wrong value");
+ break;
+ case RESULT :
+ assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+ assertSame(map.get(EXTRA_KEY), VALUES[3], "wrong value");
+ break;
+ default:
+ fail("unexpected new value");
+ }
}
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
- public void testMerge(String description, Map<IntegerEnum, String> map) {
- assertTrue(map.containsKey(KEYS[1]));
- Object value = map.get(KEYS[1]);
- assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
- assertSame(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
- assertSame(v, value);
- assertSame(vv, EXTRA_VALUE);
- return vv;
- }), EXTRA_VALUE, description);
- assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
- assertNull(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
- assertSame(v, EXTRA_VALUE);
- assertSame(vv, EXTRA_VALUE);
- return null;
- }), description);
- assertFalse(map.containsKey(KEYS[1]));
-
- assertFalse(map.containsKey(EXTRA_KEY));
- assertSame(map.merge(EXTRA_KEY, EXTRA_VALUE, (v, vv) -> {
- assertNull(v);
- assertSame(vv, EXTRA_VALUE);
- return EXTRA_VALUE;
- }), EXTRA_VALUE);
- assertTrue(map.containsKey(EXTRA_KEY));
- assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ public void testMergeNullMerger(String description, Map<IntegerEnum, String> map) {
+ assertThrows( () -> { map.merge(KEYS[1], VALUES[1], null);},
+ NullPointerException.class,
+ "Should throw NPE");
}
- @Test(expectedExceptions = {NullPointerException.class})
- public void testMergeNPEHashMap() {
- Object value = new HashMap().merge(KEYS[1], VALUES[1], null);
- }
-
- @Test(expectedExceptions = {NullPointerException.class})
- public void testMergeNPEHashtable() {
- Object value = new Hashtable().merge(KEYS[1], VALUES[1], null);
- }
-
- @Test(expectedExceptions = {NullPointerException.class})
- public void testMergeNPETreeMap() {
- Object value = new TreeMap().merge(KEYS[1], VALUES[1], null);
- }
-
- enum IntegerEnum {
+ public enum IntegerEnum {
e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
@@ -715,6 +707,89 @@
return result;
}
+ static class Merging {
+ public enum Value {
+ ABSENT,
+ NULL,
+ OLDVALUE,
+ NEWVALUE,
+ RESULT
+ }
+
+ public enum Merger implements BiFunction<String,String,String> {
+ UNUSED {
+ public String apply(String oldValue, String newValue) {
+ fail("should not be called");
+ return null;
+ }
+ },
+ NULL {
+ public String apply(String oldValue, String newValue) {
+ return null;
+ }
+ },
+ RESULT {
+ public String apply(String oldValue, String newValue) {
+ return VALUES[3];
+ }
+ },
+ }
+ }
+
+ @DataProvider(name = "MergeCases", parallel = true)
+ public Iterator<Object[]> mergeCasesProvider() {
+ Collection<Object[]> cases = new ArrayList<>();
+
+ cases.addAll(makeMergeTestCases());
+ cases.addAll(makeMergeNullValueTestCases());
+
+ return cases.iterator();
+ }
+
+ static Collection<Object[]> makeMergeTestCases() {
+ Collection<Object[]> cases = new ArrayList<>();
+
+ for( Object[] mapParams : makeAllRWMaps() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.ABSENT, Merging.Value.NEWVALUE, Merging.Merger.UNUSED, Merging.Value.NEWVALUE, Merging.Value.NEWVALUE });
+ }
+
+ for( Object[] mapParams : makeAllRWMaps() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.NULL, Merging.Value.ABSENT, Merging.Value.NULL });
+ }
+
+ for( Object[] mapParams : makeAllRWMaps() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.RESULT, Merging.Value.RESULT, Merging.Value.RESULT });
+ }
+
+ return cases;
+ }
+
+ static Collection<Object[]> makeMergeNullValueTestCases() {
+ Collection<Object[]> cases = new ArrayList<>();
+
+ for( Object[] mapParams : makeAllRWMapsWithNulls() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NULL, Merging.Merger.NULL, Merging.Value.ABSENT, Merging.Value.NULL });
+ }
+
+ for( Object[] mapParams : makeAllRWMapsWithNulls() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NULL, Merging.Merger.RESULT, Merging.Value.RESULT, Merging.Value.RESULT });
+ }
+
+ for( Object[] mapParams : makeAllRWMapsWithNulls() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.ABSENT, Merging.Value.NULL, Merging.Merger.UNUSED, Merging.Value.ABSENT, Merging.Value.NULL });
+ }
+
+ for( Object[] mapParams : makeAllRWMapsWithNulls() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.NULL, Merging.Value.NULL, Merging.Merger.UNUSED, Merging.Value.ABSENT, Merging.Value.NULL });
+ }
+
+ for( Object[] mapParams : makeAllRWMapsWithNulls() ) {
+ cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.NULL, Merging.Value.NEWVALUE, Merging.Merger.UNUSED, Merging.Value.NEWVALUE, Merging.Value.NEWVALUE });
+ }
+
+ return cases;
+ }
+
public interface Thrower<T extends Throwable> {
public void run() throws T;
diff --git a/test/java/util/Properties/LoadAndStoreXMLWithDefaults.java b/test/java/util/Properties/LoadAndStoreXMLWithDefaults.java
new file mode 100644
index 0000000..fa96e0a
--- /dev/null
+++ b/test/java/util/Properties/LoadAndStoreXMLWithDefaults.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+
+/**
+ * @test
+ * @bug 8016344
+ * @summary checks that Properties.storeToXML only stores properties locally
+ * defined on the Properties object, excluding those that are inherited.
+ * @author danielfuchs
+ */
+public class LoadAndStoreXMLWithDefaults {
+
+ public static enum StoreMethod {
+ // Note: this case will test the default provider when available,
+ // and the basic provider when it's not.
+ PROPERTIES {
+ @Override
+ public String writeToXML(Properties p) throws IOException {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ p.storeToXML(baos, "Test 8016344");
+ return baos.toString();
+ }
+ @Override
+ public Properties loadFromXML(String xml, Properties defaults)
+ throws IOException {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+ Properties p = new Properties(defaults);
+ p.loadFromXML(bais);
+ return p;
+ }
+ },
+ // Note: this case always test the basic provider, which is always available.
+ // so sometimes it's just a dup with the previous case...
+ BASICPROVIDER {
+ @Override
+ public String writeToXML(Properties p) throws IOException {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ jdk.internal.util.xml.BasicXmlPropertiesProvider provider =
+ new jdk.internal.util.xml.BasicXmlPropertiesProvider();
+ provider.store(p, baos, "Test 8016344", "UTF-8");
+ return baos.toString();
+ }
+ @Override
+ public Properties loadFromXML(String xml, Properties defaults)
+ throws IOException {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+ Properties p = new Properties(defaults);
+ jdk.internal.util.xml.BasicXmlPropertiesProvider provider =
+ new jdk.internal.util.xml.BasicXmlPropertiesProvider();
+ provider.load(p, bais);
+ return p;
+ }
+ };
+ public abstract String writeToXML(Properties p) throws IOException;
+ public abstract Properties loadFromXML(String xml, Properties defaults)
+ throws IOException;
+ public String displayName() {
+ switch(this) {
+ case PROPERTIES: return "Properties.storeToXML";
+ case BASICPROVIDER: return "BasicXmlPropertiesProvider.store";
+ default:
+ throw new UnsupportedOperationException(this.name());
+ }
+ }
+ }
+
+ static enum Objects { OBJ1, OBJ2, OBJ3 };
+
+ public static void main(String[] args) throws IOException {
+ Properties p1 = new Properties();
+ p1.setProperty("p1.prop", "prop1-p1");
+ p1.setProperty("p1.and.p2.prop", "prop2-p1");
+ p1.setProperty("p1.and.p2.and.p3.prop", "prop3-p1");
+ Properties p2 = new Properties(p1);
+ p2.setProperty("p2.prop", "prop4-p2");
+ p2.setProperty("p1.and.p2.prop", "prop5-p2");
+ p2.setProperty("p1.and.p2.and.p3.prop", "prop6-p2");
+ p2.setProperty("p2.and.p3.prop", "prop7-p2");
+ Properties p3 = new Properties(p2);
+ p3.setProperty("p3.prop", "prop8-p3");
+ p3.setProperty("p1.and.p2.and.p3.prop", "prop9-p3");
+ p3.setProperty("p2.and.p3.prop", "prop10-p3");
+
+ for (StoreMethod m : StoreMethod.values()) {
+ System.out.println("Testing with " + m.displayName());
+ Properties P1 = m.loadFromXML(m.writeToXML(p1), null);
+ Properties P2 = m.loadFromXML(m.writeToXML(p2), P1);
+ Properties P3 = m.loadFromXML(m.writeToXML(p3), P2);
+
+ testResults(m, p1, P1, p2, P2, p3, P3);
+
+ // Now check that properties whose keys or values are objects
+ // are skipped.
+
+ System.out.println("Testing with " + m.displayName() + " and Objects");
+ P1.put("p1.object.prop", Objects.OBJ1);
+ P1.put(Objects.OBJ1, "p1.object.prop");
+ P1.put("p2.object.prop", "p2.object.prop");
+ P2.put("p2.object.prop", Objects.OBJ2);
+ P2.put(Objects.OBJ2, "p2.object.prop");
+ P3.put("p3.object.prop", Objects.OBJ3);
+ P3.put(Objects.OBJ3, "p3.object.prop");
+
+ Properties PP1 = m.loadFromXML(m.writeToXML(P1), null);
+ Properties PP2 = m.loadFromXML(m.writeToXML(P2), PP1);
+ Properties PP3 = m.loadFromXML(m.writeToXML(P3), PP2);
+
+ p1.setProperty("p2.object.prop", "p2.object.prop");
+ try {
+ testResults(m, p1, PP1, p2, PP2, p3, PP3);
+ } finally {
+ p1.remove("p2.object.prop");
+ }
+ }
+ }
+
+ public static void testResults(StoreMethod m, Properties... pps) {
+ for (int i=0 ; i < pps.length ; i += 2) {
+ if (!pps[i].equals(pps[i+1])) {
+ System.err.println(m.displayName() +": P" + (i/2+1)
+ + " Reloaded properties differ from original");
+ System.err.println("\toriginal: " + pps[i]);
+ System.err.println("\treloaded: " + pps[i+1]);
+ throw new RuntimeException(m.displayName() +": P" + (i/2+1)
+ + " Reloaded properties differ from original");
+ }
+ if (!pps[i].keySet().equals(pps[i+1].keySet())) {
+ System.err.println(m.displayName() +": P" + (i/2+1)
+ + " Reloaded property names differ from original");
+ System.err.println("\toriginal: " + pps[i].keySet());
+ System.err.println("\treloaded: " + pps[i+1].keySet());
+ throw new RuntimeException(m.displayName() +": P" + (i/2+1)
+ + " Reloaded property names differ from original");
+ }
+ if (!pps[i].stringPropertyNames().equals(pps[i+1].stringPropertyNames())) {
+ System.err.println(m.displayName() +": P" + (i/2+1)
+ + " Reloaded string property names differ from original");
+ System.err.println("\toriginal: " + pps[i].stringPropertyNames());
+ System.err.println("\treloaded: " + pps[i+1].stringPropertyNames());
+ throw new RuntimeException(m.displayName() +": P" + (i/2+1)
+ + " Reloaded string property names differ from original");
+ }
+ }
+ }
+
+}
diff --git a/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh b/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh
index ea40edf..44207ab 100644
--- a/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh
+++ b/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh
@@ -40,6 +40,7 @@
${COMPILEJAVA}/bin/keytool ${TESTTOOLVMOPTS} -genkeypair -alias testcert \
-keystore ${TESTCLASSES}/timezonedatetest.store \
-storepass testpass -validity 360 \
+ -keyalg rsa \
-dname "cn=Mark Wildebeest, ou=FreeSoft, o=Red Hat, c=NL" \
-keypass testpass
diff --git a/test/java/util/concurrent/atomic/Serial.java b/test/java/util/concurrent/atomic/Serial.java
new file mode 100644
index 0000000..e0a3967
--- /dev/null
+++ b/test/java/util/concurrent/atomic/Serial.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8026344
+ * @summary Exercise classes in j.u.c.atomic that use serialization proxies
+ */
+
+import java.util.concurrent.atomic.DoubleAdder;
+import java.util.concurrent.atomic.DoubleAccumulator;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.concurrent.atomic.LongAccumulator;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.LongBinaryOperator;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+
+/**
+ * Basic test to exercise the j.u.c.atomic classes that use serialization
+ * proxies.
+ */
+
+public class Serial {
+
+ public static void main(String[] args) {
+ testDoubleAdder();
+ testDoubleAccumulator();
+ testLongAdder();
+ testLongAccumulator();
+ }
+
+ static void testDoubleAdder() {
+ DoubleAdder a = new DoubleAdder();
+ a.add(20.1d);
+ DoubleAdder result = echo(a);
+ if (result.doubleValue() != a.doubleValue())
+ throw new RuntimeException("Unexpected doubleValue");
+
+ checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAdder$SerializationProxy");
+ }
+
+ static void testDoubleAccumulator() {
+ DoubleBinaryOperator plus = (DoubleBinaryOperator & Serializable) (x, y) -> x + y;
+ DoubleAccumulator a = new DoubleAccumulator(plus, 13.9d);
+ a.accumulate(17.5d);
+ DoubleAccumulator result = echo(a);
+ if (result.get() != a.get())
+ throw new RuntimeException("Unexpected value");
+ a.reset();
+ result.reset();
+ if (result.get() != a.get())
+ throw new RuntimeException("Unexpected value after reset");
+
+ checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAccumulator$SerializationProxy");
+ }
+
+ static void testLongAdder() {
+ LongAdder a = new LongAdder();
+ a.add(45);
+ LongAdder result = echo(a);
+ if (result.longValue() != a.longValue())
+ throw new RuntimeException("Unexpected longValue");
+
+ checkSerialClassName(a, "java.util.concurrent.atomic.LongAdder$SerializationProxy");
+ }
+
+ static void testLongAccumulator() {
+ LongBinaryOperator plus = (LongBinaryOperator & Serializable) (x, y) -> x + y;
+ LongAccumulator a = new LongAccumulator(plus, -2);
+ a.accumulate(34);
+ LongAccumulator result = echo(a);
+ if (result.get() != a.get())
+ throw new RuntimeException("Unexpected value");
+ a.reset();
+ result.reset();
+ if (result.get() != a.get())
+ throw new RuntimeException("Unexpected value after reset");
+
+ checkSerialClassName(a, "java.util.concurrent.atomic.LongAccumulator$SerializationProxy");
+ }
+
+ /**
+ * Serialize the given object, returning the reconstituted object.
+ */
+ @SuppressWarnings("unchecked")
+ static <T extends Serializable> T echo(T obj) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
+ oos.writeObject(obj);
+ } catch (IOException e) {
+ throw new RuntimeException("Serialization failed: " + e);
+ }
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ try (ObjectInputStream ois = new ObjectInputStream(in)) {
+ return (T) ois.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException("Deserialization failed: " + e);
+ }
+ }
+
+ /**
+ * Checks that the given object serializes to the expected class.
+ */
+ static void checkSerialClassName(Serializable obj, String expected) {
+ String cn = serialClassName(obj);
+ if (!cn.equals(expected))
+ throw new RuntimeException(obj.getClass() + " serialized as " + cn
+ + ", expected " + expected);
+ }
+
+ /**
+ * Returns the class name that the given object serializes as.
+ */
+ static String serialClassName(Serializable obj) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
+ oos.writeObject(obj);
+ } catch (IOException e) {
+ throw new RuntimeException("Serialization failed: " + e);
+ }
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ try (DataInputStream dis = new DataInputStream(in)) {
+ dis.readShort(); // STREAM_MAGIC
+ dis.readShort(); // STREAM_VERSION
+ dis.readByte(); // TC_OBJECT
+ dis.readByte(); // TC_CLASSDESC
+ return dis.readUTF(); // className
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/test/java/util/jar/JarInputStream/ExtraFileInMetaInf.java b/test/java/util/jar/JarInputStream/ExtraFileInMetaInf.java
index f55f4c4..6a062c6 100644
--- a/test/java/util/jar/JarInputStream/ExtraFileInMetaInf.java
+++ b/test/java/util/jar/JarInputStream/ExtraFileInMetaInf.java
@@ -49,7 +49,7 @@
new File("ks").delete();
sun.security.tools.keytool.Main.main(
("-keystore ks -storepass changeit -keypass changeit " +
- "-alias a -dname CN=A -genkeypair").split(" "));
+ "-keyalg rsa -alias a -dname CN=A -genkeypair").split(" "));
sun.security.tools.jarsigner.Main.main(
"-keystore ks -storepass changeit x.jar a".split(" "));
diff --git a/test/java/util/logging/AnonymousLogger/TestAnonymousLogger.java b/test/java/util/logging/AnonymousLogger/TestAnonymousLogger.java
new file mode 100644
index 0000000..accb2b3
--- /dev/null
+++ b/test/java/util/logging/AnonymousLogger/TestAnonymousLogger.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.logging.Filter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+
+/**
+ * @test
+ * @bug 8026863
+ * @summary checks that anonymous logger setters work as expected when a
+ * security manager is set, and checks that getters return expected
+ * values.
+ * @run main/othervm TestAnonymousLogger
+ */
+public class TestAnonymousLogger {
+
+ final public static class TestHandler extends Handler {
+ @Override
+ public void publish(LogRecord record) {
+ System.out.println(new SimpleFormatter().format(record));
+ }
+ @Override
+ public void flush() {
+ System.out.flush();
+ }
+ @Override
+ public void close() {
+ flush();
+ }
+ }
+
+ final public static class TestFilter implements Filter {
+ @Override
+ public boolean isLoggable(LogRecord record) {
+ return true;
+ }
+ }
+
+ final public static class TestBundle extends ResourceBundle {
+ Set<String> keys = Collections.synchronizedSet(new LinkedHashSet<>());
+ @Override
+ protected Object handleGetObject(String key) {
+ keys.add(key);
+ return "[LOCALIZED] "+key;
+ }
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(keys);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.setSecurityManager(new SecurityManager());
+ Logger anonymous = Logger.getAnonymousLogger();
+
+ final TestHandler handler = new TestHandler();
+ final TestFilter filter = new TestFilter();
+ final ResourceBundle bundle = ResourceBundle.getBundle(TestBundle.class.getName());
+ anonymous.setLevel(Level.FINEST);
+ anonymous.addHandler(handler);
+ anonymous.setFilter(filter);
+ anonymous.setUseParentHandlers(true);
+ anonymous.setResourceBundle(bundle);
+
+ if (anonymous.getLevel() != Level.FINEST) {
+ throw new RuntimeException("Unexpected level: " + anonymous.getLevel());
+ } else {
+ System.out.println("Got expected level: " + anonymous.getLevel());
+ }
+ if (!Arrays.asList(anonymous.getHandlers()).contains(handler)) {
+ throw new RuntimeException("Expected handler not found in: "
+ + Arrays.asList(anonymous.getHandlers()));
+ } else {
+ System.out.println("Got expected handler in: " + Arrays.asList(anonymous.getHandlers()));
+ }
+ if (anonymous.getFilter() != filter) {
+ throw new RuntimeException("Unexpected filter: " + anonymous.getFilter());
+ } else {
+ System.out.println("Got expected filter: " + anonymous.getFilter());
+ }
+ if (!anonymous.getUseParentHandlers()) {
+ throw new RuntimeException("Unexpected flag: " + anonymous.getUseParentHandlers());
+ } else {
+ System.out.println("Got expected flag: " + anonymous.getUseParentHandlers());
+ }
+ if (anonymous.getResourceBundle() != bundle) {
+ throw new RuntimeException("Unexpected bundle: " + anonymous.getResourceBundle());
+ } else {
+ System.out.println("Got expected bundle: " + anonymous.getResourceBundle());
+ }
+ try {
+ anonymous.setParent(Logger.getLogger("foo.bar"));
+ throw new RuntimeException("Expected SecurityException not raised!");
+ } catch (SecurityException x) {
+ System.out.println("Got expected exception: " + x);
+ }
+ if (anonymous.getParent() != Logger.getLogger("")) {
+ throw new RuntimeException("Unexpected parent: " + anonymous.getParent());
+ } else {
+ System.out.println("Got expected parent: " + anonymous.getParent());
+ }
+ }
+
+}
diff --git a/test/java/util/logging/LogManager/RootLogger/setLevel/TestRootLoggerLevel.java b/test/java/util/logging/LogManager/RootLogger/setLevel/TestRootLoggerLevel.java
new file mode 100644
index 0000000..ec27241
--- /dev/null
+++ b/test/java/util/logging/LogManager/RootLogger/setLevel/TestRootLoggerLevel.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+
+
+
+/**
+ * @test
+ * @bug 8023163
+ * @summary checks that Logger.getLogger("").setLevel() is working correctly.
+ * @build TestRootLoggerLevel
+ * @run main/othervm -Dtest.security=on TestRootLoggerLevel
+ * @run main/othervm -Dtest.security=off TestRootLoggerLevel
+ * @author danielfuchs
+ */
+public class TestRootLoggerLevel {
+
+ public static enum Loggers {
+ ROOT("", "root"),
+ GLOBAL(Logger.GLOBAL_LOGGER_NAME);
+
+ private final String name;
+ private final String displayName;
+ Loggers(String name) {
+ this(name, name);
+ }
+ Loggers(String name, String displayName) {
+ this.name = name;
+ this.displayName = displayName;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ for (Loggers log : Loggers.values()) {
+ System.out.println(log.displayName + ": "
+ + Logger.getLogger(log.name)
+ + ": " + Logger.getLogger(log.name).getLevel());
+ }
+
+ if ("on".equals(System.getProperty("test.security","on"))) {
+ System.out.println("*** SecurityManager is ON");
+ Policy.setPolicy(new SimplePolicy());
+
+ System.setSecurityManager(new SecurityManager());
+ } else {
+ System.out.println("*** SecurityManager is OFF");
+ }
+
+ // Before the fix, setting the root logger level here had only
+ // a transient effect...
+ for (Loggers log : Loggers.values()) {
+ System.out.println("Logger.getLogger(\""
+ + log.name
+ + "\").setLevel(Level.FINEST);");
+ Logger.getLogger(log.name).setLevel(Level.FINEST);
+ System.out.println(log.displayName + ": "
+ + Logger.getLogger(log.name)
+ + ": " + Logger.getLogger(log.name).getLevel());
+
+ // At this point - the root logger should have a level which is
+ // FINEST - just check it here for sanity.
+ if (Logger.getLogger(log.name).getLevel() != Level.FINEST) {
+ throw new RuntimeException("Logger " + log.displayName
+ + " level should be FINEST: "
+ + Logger.getLogger(log.name).getLevel());
+ }
+ }
+ // Initializing some PlatformLogger caused the root logger
+ // level to be reset to INFO.
+ //
+ final Object platformLogger =
+ sun.util.logging.PlatformLogger.getLogger("java.foo");
+ System.out.println("Got platform logger: " + platformLogger);
+
+ for (Loggers log : Loggers.values()) {
+ // Check that the root logger still has the FINEST value assigned
+ // to it earlier.
+ System.out.println(log.displayName + ": "
+ + Logger.getLogger(log.name)
+ + ": " + Logger.getLogger(log.name).getLevel());
+
+ if (Logger.getLogger(log.name).getLevel() != Level.FINEST) {
+ throw new RuntimeException("Logger " + log.displayName
+ + " level should be FINEST: "
+ + Logger.getLogger(log.name).getLevel());
+ }
+ }
+
+ }
+
+ private static final class SimplePolicy extends Policy {
+ private final Permissions perms;
+
+ private static final Permissions permissions(Permission... perms) {
+ Permissions permissions = new Permissions();
+ for (Permission perm : perms) {
+ permissions.add(perm);
+ }
+ return permissions;
+ }
+
+ SimplePolicy() {
+ this(permissions(new LoggingPermission("control", null),
+ new RuntimePermission("accessClassInPackage.sun.util.logging")
+ ));
+ }
+
+ SimplePolicy(Permissions perms) {
+ this.perms = perms;
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ return perms.implies(permission);
+ }
+
+ }
+
+}
diff --git a/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java b/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
index 5423ac4..8f01dad 100644
--- a/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
+++ b/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
@@ -22,9 +22,18 @@
*/
package org.openjdk.tests.java.lang.invoke;
-import org.testng.annotations.Test;
-
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
@@ -34,6 +43,8 @@
import java.util.function.Predicate;
import java.util.function.Supplier;
+import org.testng.annotations.Test;
+
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@@ -277,4 +288,66 @@
LongConsumer lc = (LongConsumer & Serializable) a::addAndGet;
assertSerial(lc, plc -> { plc.accept(3); });
}
+
+ // Tests of direct use of metafactories
+
+ private static boolean foo(Object s) { return s != null && ((String) s).length() > 0; }
+ private static final MethodType predicateMT = MethodType.methodType(boolean.class, Object.class);
+ private static final MethodType stringPredicateMT = MethodType.methodType(boolean.class, String.class);
+ private static final Consumer<Predicate<String>> fooAsserter = x -> {
+ assertTrue(x.test("foo"));
+ assertFalse(x.test(""));
+ assertFalse(x.test(null));
+ };
+
+ // standard MF: nonserializable supertype
+ public void testDirectStdNonser() throws Throwable {
+ MethodHandle fooMH = MethodHandles.lookup().findStatic(SerializedLambdaTest.class, "foo", predicateMT);
+
+ // Standard metafactory, non-serializable target: not serializable
+ CallSite cs = LambdaMetafactory.metafactory(MethodHandles.lookup(),
+ "test", MethodType.methodType(Predicate.class),
+ predicateMT, fooMH, stringPredicateMT);
+ Predicate<String> p = (Predicate<String>) cs.getTarget().invokeExact();
+ assertNotSerial(p, fooAsserter);
+ }
+
+ // standard MF: serializable supertype
+ public void testDirectStdSer() throws Throwable {
+ MethodHandle fooMH = MethodHandles.lookup().findStatic(SerializedLambdaTest.class, "foo", predicateMT);
+
+ // Standard metafactory, serializable target: not serializable
+ CallSite cs = LambdaMetafactory.metafactory(MethodHandles.lookup(),
+ "test", MethodType.methodType(SerPredicate.class),
+ predicateMT, fooMH, stringPredicateMT);
+ assertNotSerial((SerPredicate<String>) cs.getTarget().invokeExact(), fooAsserter);
+ }
+
+ // alt MF: nonserializable supertype
+ public void testAltStdNonser() throws Throwable {
+ MethodHandle fooMH = MethodHandles.lookup().findStatic(SerializedLambdaTest.class, "foo", predicateMT);
+
+ // Alt metafactory, non-serializable target: not serializable
+ CallSite cs = LambdaMetafactory.altMetafactory(MethodHandles.lookup(),
+ "test", MethodType.methodType(Predicate.class),
+ predicateMT, fooMH, stringPredicateMT, 0);
+ assertNotSerial((Predicate<String>) cs.getTarget().invokeExact(), fooAsserter);
+ }
+
+ // alt MF: serializable supertype
+ public void testAltStdSer() throws Throwable {
+ MethodHandle fooMH = MethodHandles.lookup().findStatic(SerializedLambdaTest.class, "foo", predicateMT);
+
+ // Alt metafactory, serializable target, no FLAG_SERIALIZABLE: not serializable
+ CallSite cs = LambdaMetafactory.altMetafactory(MethodHandles.lookup(),
+ "test", MethodType.methodType(SerPredicate.class),
+ predicateMT, fooMH, stringPredicateMT, 0);
+ assertNotSerial((SerPredicate<String>) cs.getTarget().invokeExact(), fooAsserter);
+
+ // Alt metafactory, serializable marker, no FLAG_SERIALIZABLE: not serializable
+ cs = LambdaMetafactory.altMetafactory(MethodHandles.lookup(),
+ "test", MethodType.methodType(Predicate.class),
+ predicateMT, fooMH, stringPredicateMT, LambdaMetafactory.FLAG_MARKERS, 1, Serializable.class);
+ assertNotSerial((Predicate<String>) cs.getTarget().invokeExact(), fooAsserter);
+ }
}
diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
index 8d9e3f8..7d26925 100644
--- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
+++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
@@ -28,8 +28,10 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
+import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.*;
import static java.util.stream.LambdaTestHelpers.*;
@@ -48,6 +50,17 @@
assertCountSum(countTo(10).stream().distinct(), 10, 55);
}
+ public void testWithUnorderedInfiniteStream() {
+ // These tests should short-circuit, otherwise will fail with a time-out
+ // or an OOME
+
+ Integer one = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny().get();
+ assertEquals(one.intValue(), 1);
+
+ Optional<Integer> oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny();
+ assertTrue(oi.isPresent());
+ }
+
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
public void testOp(String name, TestData.OfRef<Integer> data) {
Collection<Integer> result = exerciseOpsInt(data, Stream::distinct, IntStream::distinct, LongStream::distinct, DoubleStream::distinct);
diff --git a/test/java/util/zip/GZIP/GZIPInZip.java b/test/java/util/zip/GZIP/GZIPInZip.java
index fab869a..12be4c8 100644
--- a/test/java/util/zip/GZIP/GZIPInZip.java
+++ b/test/java/util/zip/GZIP/GZIPInZip.java
@@ -22,15 +22,14 @@
*/
/* @test
- * @bug 7021870 8023431
+ * @bug 7021870 8023431 8026756
* @summary Reading last gzip chain member must not close the input stream.
* Garbage following gzip entry must be ignored.
*/
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
@@ -40,9 +39,9 @@
public class GZIPInZip {
- private static volatile Throwable trouble;
+ public static void main(String[] args)
+ throws Throwable {
- public static void main(String[] args) throws Throwable {
doTest(false, false);
doTest(false, true);
doTest(true, false);
@@ -53,63 +52,46 @@
final boolean limitGISBuff)
throws Throwable {
- final PipedOutputStream pos = new PipedOutputStream();
- final PipedInputStream pis = new PipedInputStream(pos);
+ byte[] buf;
- Thread compressor = new Thread() {
- public void run() {
- final byte[] xbuf = { 'x' };
- try (ZipOutputStream zos = new ZipOutputStream(pos)) {
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(baos)) {
- zos.putNextEntry(new ZipEntry("a.gz"));
- try (GZIPOutputStream gos1 = new GZIPOutputStream(zos)) {
- gos1.write(xbuf);
- gos1.finish();
- }
- if (appendGarbage)
- zos.write(xbuf);
+ final byte[] xbuf = { 'x' };
- zos.closeEntry();
+ zos.putNextEntry(new ZipEntry("a.gz"));
+ GZIPOutputStream gos1 = new GZIPOutputStream(zos);
+ gos1.write(xbuf);
+ gos1.finish();
+ if (appendGarbage)
+ zos.write(xbuf);
+ zos.closeEntry();
- zos.putNextEntry(new ZipEntry("b.gz"));
- try (GZIPOutputStream gos2 = new GZIPOutputStream(zos)) {
- gos2.write(xbuf);
- gos2.finish();
- }
- zos.closeEntry();
+ zos.putNextEntry(new ZipEntry("b.gz"));
+ GZIPOutputStream gos2 = new GZIPOutputStream(zos);
+ gos2.write(xbuf);
+ gos2.finish();
+ zos.closeEntry();
- } catch (Throwable t) {
- trouble = t;
- }
+ zos.flush();
+ buf = baos.toByteArray();
+ }
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+ ZipInputStream zis = new ZipInputStream(bais)) {
+
+ zis.getNextEntry();
+ GZIPInputStream gis1 = limitGISBuff ?
+ new GZIPInputStream(zis, 4) :
+ new GZIPInputStream(zis);
+ // try to read more than the entry has
+ gis1.skip(2);
+
+ try {
+ zis.getNextEntry();
+ } catch (IOException e) {
+ throw new RuntimeException("ZIP stream was prematurely closed", e);
}
- };
-
- Thread uncompressor = new Thread() {
- public void run() {
- try (ZipInputStream zis = new ZipInputStream(pis)) {
- zis.getNextEntry();
- try (InputStream gis = limitGISBuff ?
- new GZIPInputStream(zis, 4) :
- new GZIPInputStream(zis)) {
- // try to read more than the entry has
- gis.skip(2);
- }
-
- try {
- zis.getNextEntry();
- } catch (IOException e) {
- throw new AssertionError("ZIP stream was prematurely closed");
- }
- } catch (Throwable t) {
- trouble = t;
- }
- }
- };
-
- compressor.start(); uncompressor.start();
- compressor.join(); uncompressor.join();
-
- if (trouble != null)
- throw trouble;
+ }
}
}
diff --git a/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java b/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java
index 91ec8fa..ae94557 100644
--- a/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java
+++ b/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -25,49 +25,48 @@
* @test
* @summary NPE IN RMIConnector.connect
* @bug 6984520
+ * @library /java/rmi/testlibrary
* @run clean RMIConnector_NPETest
+ * @run build TestLibrary RMID
* @run build RMIConnector_NPETest
* @run main RMIConnector_NPETest
*/
-
-import java.io.*;
-import java.lang.management.*;
-import java.rmi.registry.*;
+import java.io.IOException;
import javax.management.*;
-import javax.management.remote.*;
import javax.management.remote.rmi.*;
-public class RMIConnector_NPETest {
-
+public class RMIConnector_NPETest {
public static void main(String argv[]) throws Exception {
- boolean testFailed = false;
- String rmidCmd = System.getProperty("java.home") + File.separator +
- "bin" + File.separator + "rmid -port 3333";
- String stopRmidCmd = System.getProperty("java.home") + File.separator +
- "bin" + File.separator + "rmid -stop -port 3333";
- try {
- //start an rmid daemon and give it some time
- System.out.println("Starting rmid");
- Runtime.getRuntime().exec(rmidCmd);
- Thread.sleep(5000);
+ RMID rmid = RMID.createRMID();
+ rmid.start();
+ int rmidPort = rmid.getPort();
+ Exception failureCause = null;
+ RMIConnector agent = null;
- MBeanServer mbs = MBeanServerFactory.createMBeanServer();
- RMIJRMPServerImpl rmiserver = new RMIJRMPServerImpl(3333, null, null, null);
- rmiserver.setMBeanServer(mbs);
- RMIConnector agent = new RMIConnector(rmiserver, null);
- agent.connect();
- } catch(NullPointerException npe) {
- npe.printStackTrace();
- testFailed = true;
- } catch (Exception e) {
- // OK
- } finally {
- System.out.println("Stopping rmid");
- Runtime.getRuntime().exec(stopRmidCmd);
+ try {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ RMIJRMPServerImpl rmiserver = new RMIJRMPServerImpl(rmidPort, null, null, null);
+ rmiserver.setMBeanServer(mbs);
+ agent = new RMIConnector(rmiserver, null);
+ agent.connect();
+ } catch (NullPointerException npe) {
+ failureCause = npe;
+ } catch (Exception e) {
+ // OK
+ } finally {
+ if (agent != null) {
+ try {
+ agent.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ rmid.shutdown(rmidPort);
}
- if(testFailed)
- throw new Exception("Test failed");
+ if (failureCause != null) {
+ TestLibrary.bomb("Test failed", failureCause);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java b/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
index 5901469..24bf863 100644
--- a/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
+++ b/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -33,8 +33,8 @@
// java imports
//
-import java.io.IOException;
import java.net.MalformedURLException;
+import java.util.Map;
// JMX imports
//
@@ -44,7 +44,7 @@
import javax.management.remote.JMXServiceURL;
public class NotSerializableNotifTest {
- private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
+ private static final MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
private static ObjectName emitter;
private static int port = 2468;
@@ -52,9 +52,19 @@
private static final int sentNotifs = 10;
+ private static double timeoutFactor = 1.0;
+ private static final double defaultTimeout = 10;
+
public static void main(String[] args) throws Exception {
System.out.println(">>> Test to send a not serializable notification");
+ String timeoutVal = System.getProperty("test.timeout.factor");
+ if (timeoutVal != null) {
+ timeoutFactor = Double.parseDouble(
+ System.getProperty("test.timeout.factor")
+ );
+ }
+
// IIOP fails on JDK1.4, see 5034318
final String v = System.getProperty("java.version");
float f = Float.parseFloat(v.substring(0, 3));
@@ -136,7 +146,8 @@
// waiting ...
synchronized (listener) {
- for (int i=0; i<10; i++) {
+ int top = (int)Math.ceil(timeoutFactor * defaultTimeout);
+ for (int i=0; i<top; i++) {
if (listener.received() < sentNotifs) {
listener.wait(1000);
} else {
diff --git a/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java b/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
index 4fe2659..ba12d0d 100644
--- a/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
+++ b/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
@@ -65,7 +65,7 @@
String inFilename = filePath + "/JDK8022548.xml";
String xslFilename = filePath + "/JDK8022548.xsl";
- String outFilename = filePath + "/JDK8022548.out";
+ String outFilename = "JDK8022548.out";
StringWriter sw = new StringWriter();
// Create transformer factory
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/SecureProcessingTest.xml b/test/javax/xml/jaxp/transform/jdk8004476/SecureProcessingTest.xml
new file mode 100644
index 0000000..bc916a9
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/SecureProcessingTest.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<helloWorld/>
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/TestBase.java b/test/javax/xml/jaxp/transform/jdk8004476/TestBase.java
new file mode 100644
index 0000000..4b6ea70
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/TestBase.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+import java.security.Policy;
+
+/**
+ *
+ *
+ * @author huizhe.wang@oracle.com
+ */
+public class TestBase {
+ public static boolean isWindows = false;
+ static {
+ if (System.getProperty("os.name").indexOf("Windows")>-1) {
+ isWindows = true;
+ }
+ };
+
+ String filepath;
+ boolean hasSM;
+ String curDir;
+ Policy origPolicy;
+ String testName;
+ static String errMessage;
+
+ int passed = 0, failed = 0;
+
+ /**
+ * Creates a new instance of StreamReader
+ */
+ public TestBase(String name) {
+ testName = name;
+ }
+
+ //junit @Override
+ protected void setUp() {
+ if (System.getSecurityManager() != null) {
+ hasSM = true;
+ System.setSecurityManager(null);
+ }
+
+ filepath = System.getProperty("test.src");
+ if (filepath == null) {
+ //current directory
+ filepath = System.getProperty("user.dir");
+ }
+ origPolicy = Policy.getPolicy();
+
+ }
+
+ //junit @Override
+ public void tearDown() {
+ // turn off security manager and restore policy
+ System.setSecurityManager(null);
+ Policy.setPolicy(origPolicy);
+ if (hasSM) {
+ System.setSecurityManager(new SecurityManager());
+ }
+ System.out.println("\nNumber of tests passed: " + passed);
+ System.out.println("Number of tests failed: " + failed + "\n");
+
+ if (errMessage != null ) {
+ throw new RuntimeException(errMessage);
+ }
+ }
+
+ void fail(String errMsg) {
+ if (errMessage == null) {
+ errMessage = errMsg;
+ } else {
+ errMessage = errMessage + "\n" + errMsg;
+ }
+ failed++;
+ }
+
+ void success(String msg) {
+ passed++;
+ System.out.println(msg);
+ }
+
+}
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/XPathExFuncTest.java b/test/javax/xml/jaxp/transform/jdk8004476/XPathExFuncTest.java
new file mode 100644
index 0000000..5680067
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/XPathExFuncTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8004476
+ * @summary test XPath extension functions
+ * @run main/othervm XPathExFuncTest
+ */
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFactoryConfigurationException;
+import javax.xml.xpath.XPathFunction;
+import javax.xml.xpath.XPathFunctionException;
+import javax.xml.xpath.XPathFunctionResolver;
+import org.w3c.dom.Document;
+
+/**
+ * test XPath extension functions
+ *
+ * @author huizhe.wang@oracle.com
+ */
+public class XPathExFuncTest extends TestBase {
+
+ final static String ENABLE_EXTENSION_FUNCTIONS = "http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions";
+ final static String CLASSNAME = "DocumentBuilderFactoryImpl";
+ final String XPATH_EXPRESSION = "ext:helloWorld()";
+
+ /**
+ * Creates a new instance of StreamReader
+ */
+ public XPathExFuncTest(String name) {
+ super(name);
+ }
+ boolean hasSM;
+ String xslFile, xslFileId;
+ String xmlFile, xmlFileId;
+
+ protected void setUp() {
+ super.setUp();
+ xmlFile = filepath + "/SecureProcessingTest.xml";
+
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ XPathExFuncTest test = new XPathExFuncTest("OneTest");
+ test.setUp();
+
+ test.testExtFunc();
+ test.testExtFuncNotAllowed();
+ test.testEnableExtFunc();
+ test.tearDown();
+
+ }
+
+ /**
+ * by default, extension function is enabled
+ */
+ public void testExtFunc() {
+
+ try {
+ evaluate(false);
+ System.out.println("testExtFunc: OK");
+ } catch (XPathFactoryConfigurationException e) {
+ fail(e.getMessage());
+ } catch (XPathExpressionException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ /**
+ * Security is enabled, extension function not allowed
+ */
+ public void testExtFuncNotAllowed() {
+ Policy p = new SimplePolicy(new AllPermission());
+ Policy.setPolicy(p);
+ System.setSecurityManager(new SecurityManager());
+
+ try {
+ evaluate(false);
+ } catch (XPathFactoryConfigurationException e) {
+ fail(e.getMessage());
+ } catch (XPathExpressionException ex) {
+ //expected since extension function is disallowed
+ System.out.println("testExtFuncNotAllowed: OK");
+ } finally {
+ System.setSecurityManager(null);
+ }
+ }
+
+ /**
+ * Security is enabled, use new feature: enableExtensionFunctions
+ */
+ public void testEnableExtFunc() {
+ Policy p = new SimplePolicy(new AllPermission());
+ Policy.setPolicy(p);
+ System.setSecurityManager(new SecurityManager());
+
+
+ try {
+ evaluate(true);
+ System.out.println("testEnableExt: OK");
+ } catch (XPathFactoryConfigurationException e) {
+ fail(e.getMessage());
+ } catch (XPathExpressionException e) {
+ fail(e.getMessage());
+ } finally {
+ System.setSecurityManager(null);
+ }
+ }
+
+ Document getDocument() {
+ // the xml source
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = null;
+ Document document = null;
+
+ try {
+ documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ InputStream xmlStream = new FileInputStream(xmlFile);
+ document = documentBuilder.parse(xmlStream);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ return document;
+ }
+
+ void evaluate(boolean enableExt) throws XPathFactoryConfigurationException, XPathExpressionException {
+ Document document = getDocument();
+
+ XPathFactory xPathFactory = XPathFactory.newInstance();
+ /**
+ * Use of the extension function 'http://exslt.org/strings:tokenize' is
+ * not allowed when the secure processing feature is set to true.
+ * Attempt to use the new property to enable extension function
+ */
+ if (enableExt) {
+ boolean isExtensionSupported = enableExtensionFunction(xPathFactory);
+ }
+
+ xPathFactory.setXPathFunctionResolver(new MyXPathFunctionResolver());
+ if (System.getSecurityManager() == null) {
+ xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
+ }
+
+ XPath xPath = xPathFactory.newXPath();
+ xPath.setNamespaceContext(new MyNamespaceContext());
+
+ String xPathResult = xPath.evaluate(XPATH_EXPRESSION, document);
+ System.out.println(
+ "XPath result (enableExtensionFunction == " + enableExt + ") = \""
+ + xPathResult
+ + "\"");
+ }
+
+ public class MyXPathFunctionResolver
+ implements XPathFunctionResolver {
+
+ public XPathFunction resolveFunction(QName functionName, int arity) {
+
+ // not a real ewsolver, always return a default XPathFunction
+ return new MyXPathFunction();
+ }
+ }
+
+ public class MyXPathFunction
+ implements XPathFunction {
+
+ public Object evaluate(List list) throws XPathFunctionException {
+
+ return "Hello World";
+ }
+ }
+
+ public class MyNamespaceContext implements NamespaceContext {
+
+ public String getNamespaceURI(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException("The prefix cannot be null.");
+ }
+
+ if (prefix.equals("ext")) {
+ return "http://ext.com";
+ } else {
+ return null;
+ }
+ }
+
+ public String getPrefix(String namespace) {
+
+ if (namespace == null) {
+ throw new IllegalArgumentException("The namespace uri cannot be null.");
+ }
+
+ if (namespace.equals("http://ext.com")) {
+ return "ext";
+ } else {
+ return null;
+ }
+ }
+
+ public Iterator getPrefixes(String namespace) {
+ return null;
+ }
+ }
+
+ boolean enableExtensionFunction(XPathFactory factory) {
+ boolean isSupported = true;
+ try {
+ factory.setFeature(ENABLE_EXTENSION_FUNCTIONS, true);
+ } catch (XPathFactoryConfigurationException ex) {
+ isSupported = false;
+ }
+ return isSupported;
+ }
+
+ class SimplePolicy extends Policy {
+
+ private final Permissions perms;
+
+ public SimplePolicy(Permission... permissions) {
+ perms = new Permissions();
+ for (Permission permission : permissions) {
+ perms.add(permission);
+ }
+ }
+
+ @Override
+ public PermissionCollection getPermissions(CodeSource cs) {
+ return perms;
+ }
+
+ @Override
+ public PermissionCollection getPermissions(ProtectionDomain pd) {
+ return perms;
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain pd, Permission p) {
+ return perms.implies(p);
+ }
+
+ //for older jdk
+ @Override
+ public void refresh() {
+ }
+ }
+}
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/XSLTExFuncTest.java b/test/javax/xml/jaxp/transform/jdk8004476/XSLTExFuncTest.java
new file mode 100644
index 0000000..3565ba7
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/XSLTExFuncTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8004476
+ * @summary test XSLT extension functions
+ * @run main/othervm XSLTExFuncTest
+ */
+
+import java.io.StringWriter;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import javax.xml.transform.*;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import org.xml.sax.InputSource;
+
+/**
+ * test XSLT extension functions
+ *
+ * @author huizhe.wang@oracle.com
+ */
+public class XSLTExFuncTest extends TestBase {
+
+ final static String ENABLE_EXTENSION_FUNCTIONS = "http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions";
+ final static String CLASSNAME = "DocumentBuilderFactoryImpl";
+
+ /**
+ * Creates a new instance of StreamReader
+ */
+ public XSLTExFuncTest(String name) {
+ super(name);
+ }
+ boolean hasSM;
+ String xslFile, xslFileId;
+ String xmlFile, xmlFileId;
+
+ protected void setUp() {
+ super.setUp();
+ xmlFile = filepath + "/tokenize.xml";
+ xslFile = filepath + "/tokenize.xsl";
+
+ /**
+ * if (isWindows) { xslFile = "/" + xslFile; }
+ *
+ */
+ xslFileId = "file://" + xslFile;
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ XSLTExFuncTest test = new XSLTExFuncTest("OneTest");
+ test.setUp();
+
+ test.testExtFunc();
+ test.testExtFuncNotAllowed();
+ test.testEnableExtFunc();
+ test.testTemplatesEnableExtFunc();
+ test.tearDown();
+
+ }
+
+ /**
+ * by default, extension function is enabled
+ */
+ public void testExtFunc() {
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ try {
+ transform(factory);
+ System.out.println("testExtFunc: OK");
+ } catch (TransformerConfigurationException e) {
+ fail(e.getMessage());
+ } catch (TransformerException ex) {
+ fail(ex.getMessage());
+ }
+ }
+
+ /**
+ * Security is enabled, extension function not allowed
+ */
+ public void testExtFuncNotAllowed() {
+ Policy p = new SimplePolicy(new AllPermission());
+ Policy.setPolicy(p);
+ System.setSecurityManager(new SecurityManager());
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ try {
+ transform(factory);
+ } catch (TransformerConfigurationException e) {
+ fail(e.getMessage());
+ } catch (TransformerException ex) {
+ //expected since extension function is disallowed
+ System.out.println("testExtFuncNotAllowed: OK");
+ } finally {
+ System.setSecurityManager(null);
+ }
+ }
+
+ /**
+ * Security is enabled, use new feature: enableExtensionFunctions
+ */
+ public void testEnableExtFunc() {
+ Policy p = new SimplePolicy(new AllPermission());
+ Policy.setPolicy(p);
+ System.setSecurityManager(new SecurityManager());
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ /**
+ * Use of the extension function 'http://exslt.org/strings:tokenize' is
+ * not allowed when the secure processing feature is set to true.
+ * Attempt to use the new property to enable extension function
+ */
+ boolean isExtensionSupported = enableExtensionFunction(factory);
+
+ try {
+ transform(factory);
+ System.out.println("testEnableExt: OK");
+ } catch (TransformerConfigurationException e) {
+ fail(e.getMessage());
+ } catch (TransformerException e) {
+ fail(e.getMessage());
+ } finally {
+ System.setSecurityManager(null);
+ }
+ }
+
+ /**
+ * use Templates template = factory.newTemplates(new StreamSource( new
+ * FileInputStream(xslFilename))); // Use the template to create a
+ * transformer Transformer xformer = template.newTransformer();
+ *
+ * @param factory
+ * @return
+ */
+ /**
+ * Security is enabled, use new feature: enableExtensionFunctions Use the
+ * template to create a transformer
+ */
+ public void testTemplatesEnableExtFunc() {
+ Policy p = new SimplePolicy(new AllPermission());
+ Policy.setPolicy(p);
+ System.setSecurityManager(new SecurityManager());
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ /**
+ * Use of the extension function 'http://exslt.org/strings:tokenize' is
+ * not allowed when the secure processing feature is set to true.
+ * Attempt to use the new property to enable extension function
+ */
+ boolean isExtensionSupported = enableExtensionFunction(factory);
+
+ try {
+ SAXSource xslSource = new SAXSource(new InputSource(xslFile));
+ xslSource.setSystemId(xslFileId);
+ Templates template = factory.newTemplates(xslSource);
+ Transformer transformer = template.newTransformer();
+ StringWriter stringResult = new StringWriter();
+ Result result = new StreamResult(stringResult);
+ transformer.transform(new SAXSource(new InputSource(xmlFile)), result);
+ System.out.println("testTemplatesEnableExtFunc: OK");
+ } catch (TransformerConfigurationException e) {
+ fail(e.getMessage());
+ } catch (TransformerException e) {
+ fail(e.getMessage());
+ } finally {
+ System.setSecurityManager(null);
+ }
+ }
+
+ boolean enableExtensionFunction(TransformerFactory factory) {
+ boolean isSupported = true;
+ try {
+ factory.setFeature(ENABLE_EXTENSION_FUNCTIONS, true);
+ } catch (TransformerConfigurationException ex) {
+ isSupported = false;
+ }
+ return isSupported;
+ }
+
+ void transform(TransformerFactory factory) throws TransformerConfigurationException, TransformerException {
+ SAXSource xslSource = new SAXSource(new InputSource(xslFile));
+ xslSource.setSystemId(xslFileId);
+ Transformer transformer = factory.newTransformer(xslSource);
+ StringWriter stringResult = new StringWriter();
+ Result result = new StreamResult(stringResult);
+ transformer.transform(new SAXSource(new InputSource(xmlFile)), result);
+ }
+
+ class SimplePolicy extends Policy {
+
+ private final Permissions perms;
+
+ public SimplePolicy(Permission... permissions) {
+ perms = new Permissions();
+ for (Permission permission : permissions) {
+ perms.add(permission);
+ }
+ }
+
+ @Override
+ public PermissionCollection getPermissions(CodeSource cs) {
+ return perms;
+ }
+
+ @Override
+ public PermissionCollection getPermissions(ProtectionDomain pd) {
+ return perms;
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain pd, Permission p) {
+ return perms.implies(p);
+ }
+
+ //for older jdk
+ @Override
+ public void refresh() {
+ }
+ }
+}
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xml b/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xml
new file mode 100644
index 0000000..646335e
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<html>
+<a>
+ <b>Is this EXSLT? No. no</b>
+ <c>Is this EXSLT? No. no</c>
+</a>
+</html>
\ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xsl b/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xsl
new file mode 100644
index 0000000..d090d3b
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/jdk8004476/tokenize.xsl
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ version="1.0">
+<xsl:template match="a">
+ <xsl:apply-templates />
+</xsl:template>
+<xsl:template match="//a/c">
+ <xsl:value-of select="." />
+ -
+ <xsl:value-of select="str:tokenize(string(.), ' ')" />
+ <xsl:value-of select="str:tokenize(string(.), '')" />
+ <xsl:for-each select="str:tokenize(string(.), ' ')">
+ <xsl:value-of select="." />
+ </xsl:for-each>
+ <xsl:apply-templates select="*" />
+</xsl:template>
+<xsl:template match="//a/b">
+ <xsl:value-of select="." />
+ -
+ <xsl:value-of select="xalan:tokenize(string(.), ' ')" />
+ <xsl:value-of select="xalan:tokenize(string(.), '')" />
+ <xsl:for-each select="xalan:tokenize(string(.), ' ')">
+ <xsl:value-of select="." />
+ </xsl:for-each>
+ <xsl:apply-templates select="*" />
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/test/javax/xml/ws/clientjar/TestWsImport.java b/test/javax/xml/ws/clientjar/TestWsImport.java
index add1c2a..422f4f5 100644
--- a/test/javax/xml/ws/clientjar/TestWsImport.java
+++ b/test/javax/xml/ws/clientjar/TestWsImport.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8016271
+ * @bug 8016271 8026405
* @summary wsimport -clientjar does not create portable jar on windows due to hardcoded '\'
* @run main/othervm TestWsImport
*/
@@ -77,14 +77,14 @@
String address = "http://localhost:" + port + "/hello";
Service service = Service.create(new URL(address + "?wsdl"),
- new QName("http://test/jaxws/sample/",
- "TestService"));
+ new QName("http://test/jaxws/sample/", "TestService"));
String[] wsargs = {
wsimport,
"-p",
"wstest",
"-J-Djavax.xml.accessExternalSchema=all",
+ "-J-Dcom.sun.tools.internal.ws.Invoker.noSystemProxies=true",
address + "?wsdl",
"-clientjar",
"wsjar.jar"
diff --git a/test/jdk/lambda/vm/DefaultMethodsTest.java b/test/jdk/lambda/vm/DefaultMethodsTest.java
deleted file mode 100644
index aabd8f9..0000000
--- a/test/jdk/lambda/vm/DefaultMethodsTest.java
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- * 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 vm;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.io.File;
-import java.io.IOException;
-
-import org.testng.annotations.Test;
-import separate.*;
-import separate.Compiler;
-
-import static org.testng.Assert.*;
-import static separate.SourceModel.*;
-import static separate.SourceModel.Class;
-
-@Test(groups = "vm")
-public class DefaultMethodsTest extends TestHarness {
- public DefaultMethodsTest() {
- super(false, false);
- }
-
- /**
- * class C { public int m() { return 22; } }
- *
- * TEST: C c = new C(); c.m() == 22
- */
- public void testHarnessInvokeVirtual() {
- Class C = new Class("C", ConcreteMethod.std("22"));
- assertInvokeVirtualEquals(22, C);
- }
-
- /**
- * interface I { int m(); }
- * class C implements I { public int m() { return 33; } }
- *
- * TEST: I i = new C(); i.m() == 33;
- */
- public void testHarnessInvokeInterface() {
- Interface I = new Interface("I", AbstractMethod.std());
- Class C = new Class("C", I, ConcreteMethod.std("33"));
- assertInvokeInterfaceEquals(33, C, I);
- }
-
- /**
- * class C {}
- *
- * TEST: C c = new C(); c.m() throws NoSuchMethod
- */
- public void testHarnessThrows() {
- Class C = new Class("C");
- assertThrows(NoSuchMethodError.class, C);
- }
-
- /**
- * interface I { int m() default { return 44; } }
- * class C implements I {}
- *
- * TEST: C c = new C(); c.m() == 44;
- * TEST: I i = new C(); i.m() == 44;
- */
- public void testBasicDefault() {
- Interface I = new Interface("I", DefaultMethod.std("44"));
- Class C = new Class("C", I);
-
- assertInvokeVirtualEquals(44, C);
- assertInvokeInterfaceEquals(44, C, I);
- }
-
- /**
- * interface I { default int m() { return 44; } }
- * interface J extends I {}
- * interface K extends J {}
- * class C implements K {}
- *
- * TEST: C c = new C(); c.m() == 44;
- * TEST: I i = new C(); i.m() == 44;
- */
- public void testFarDefault() {
- Interface I = new Interface("I", DefaultMethod.std("44"));
- Interface J = new Interface("J", I);
- Interface K = new Interface("K", J);
- Class C = new Class("C", K);
-
- assertInvokeVirtualEquals(44, C);
- assertInvokeInterfaceEquals(44, C, K);
- }
-
- /**
- * interface I { int m(); }
- * interface J extends I { default int m() { return 44; } }
- * interface K extends J {}
- * class C implements K {}
- *
- * TEST: C c = new C(); c.m() == 44;
- * TEST: K k = new C(); k.m() == 44;
- */
- public void testOverrideAbstract() {
- Interface I = new Interface("I", AbstractMethod.std());
- Interface J = new Interface("J", I, DefaultMethod.std("44"));
- Interface K = new Interface("K", J);
- Class C = new Class("C", K);
-
- assertInvokeVirtualEquals(44, C);
- assertInvokeInterfaceEquals(44, C, K);
- }
-
- /**
- * interface I { int m() default { return 44; } }
- * class C implements I { public int m() { return 55; } }
- *
- * TEST: C c = new C(); c.m() == 55;
- * TEST: I i = new C(); i.m() == 55;
- */
- public void testExisting() {
- Interface I = new Interface("I", DefaultMethod.std("44"));
- Class C = new Class("C", I, ConcreteMethod.std("55"));
-
- assertInvokeVirtualEquals(55, C);
- assertInvokeInterfaceEquals(55, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * class B implements I {}
- * class C extends B {}
- *
- * TEST: C c = new C(); c.m() == 99;
- * TEST: I i = new C(); i.m() == 99;
- */
- public void testInherited() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Class B = new Class("B", I);
- Class C = new Class("C", B);
-
- assertInvokeVirtualEquals(99, C);
- assertInvokeInterfaceEquals(99, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * class C { public int m() { return 11; } }
- * class D extends C implements I {}
- *
- * TEST: D d = new D(); d.m() == 11;
- * TEST: I i = new D(); i.m() == 11;
- */
- public void testExistingInherited() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Class C = new Class("C", ConcreteMethod.std("11"));
- Class D = new Class("D", C, I);
-
- assertInvokeVirtualEquals(11, D);
- assertInvokeInterfaceEquals(11, D, I);
- }
-
- /**
- * interface I { default int m() { return 44; } }
- * class C implements I { public int m() { return 11; } }
- * class D extends C { public int m() { return 22; } }
- *
- * TEST: D d = new D(); d.m() == 22;
- * TEST: I i = new D(); i.m() == 22;
- */
- void testExistingInheritedOverride() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Class C = new Class("C", I, ConcreteMethod.std("11"));
- Class D = new Class("D", C, ConcreteMethod.std("22"));
-
- assertInvokeVirtualEquals(22, D);
- assertInvokeInterfaceEquals(22, D, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * interface J { defaultint m() { return 88; } }
- * class C implements I { public int m() { return 11; } }
- * class D extends C { public int m() { return 22; } }
- * class E extends D implements J {}
- *
- * TEST: E e = new E(); e.m() == 22;
- * TEST: J j = new E(); j.m() == 22;
- */
- public void testExistingInheritedPlusDefault() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", DefaultMethod.std("88"));
- Class C = new Class("C", I, ConcreteMethod.std("11"));
- Class D = new Class("D", C, ConcreteMethod.std("22"));
- Class E = new Class("E", D, J);
-
- assertInvokeVirtualEquals(22, E);
- assertInvokeInterfaceEquals(22, E, J);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * class B implements I {}
- * class C extends B { public int m() { return 77; } }
- *
- * TEST: C c = new C(); c.m() == 77;
- * TEST: I i = new C(); i.m() == 77;
- */
- public void testInheritedWithConcrete() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Class B = new Class("B", I);
- Class C = new Class("C", B, ConcreteMethod.std("77"));
-
- assertInvokeVirtualEquals(77, C);
- assertInvokeInterfaceEquals(77, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * class B implements I {}
- * class C extends B implements I { public int m() { return 66; } }
- *
- * TEST: C c = new C(); c.m() == 66;
- * TEST: I i = new C(); i.m() == 66;
- */
- public void testInheritedWithConcreteAndImpl() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Class B = new Class("B", I);
- Class C = new Class("C", B, I, ConcreteMethod.std("66"));
-
- assertInvokeVirtualEquals(66, C);
- assertInvokeInterfaceEquals(66, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * interface J { default int m() { return 88; } }
- * class C implements I, J {}
- *
- * TEST: C c = new C(); c.m() throws AME
- */
- public void testConflict() {
- // debugTest();
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", DefaultMethod.std("88"));
- Class C = new Class("C", I, J);
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface I { int m(); }
- * interface J { default int m() { return 88; } }
- * class C implements I, J {}
- *
- * TEST: C c = new C(); c.m() throws AME
- */
- public void testAmbiguousReabstract() {
- Interface I = new Interface("I", AbstractMethod.std());
- Interface J = new Interface("J", DefaultMethod.std("88"));
- Class C = new Class("C", I, J);
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * interface J extends I { }
- * interface K extends I { }
- * class C implements J, K {}
- *
- * TEST: C c = new C(); c.m() == 99
- * TEST: J j = new C(); j.m() == 99
- * TEST: K k = new C(); k.m() == 99
- * TEST: I i = new C(); i.m() == 99
- */
- public void testDiamond() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", I);
- Interface K = new Interface("K", I);
- Class C = new Class("C", J, K);
-
- assertInvokeVirtualEquals(99, C);
- assertInvokeInterfaceEquals(99, C, J);
- assertInvokeInterfaceEquals(99, C, K);
- assertInvokeInterfaceEquals(99, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * interface J extends I { }
- * interface K extends I { }
- * interface L extends I { }
- * interface M extends I { }
- * class C implements I, J, K, L, M {}
- *
- * TEST: C c = new C(); c.m() == 99
- * TEST: J j = new C(); j.m() == 99
- * TEST: K k = new C(); k.m() == 99
- * TEST: I i = new C(); i.m() == 99
- * TEST: L l = new C(); l.m() == 99
- * TEST: M m = new C(); m.m() == 99
- */
- public void testExpandedDiamond() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", I);
- Interface K = new Interface("K", I);
- Interface L = new Interface("L", I);
- Interface M = new Interface("M", L);
- Class C = new Class("C", I, J, K, L, M);
-
- assertInvokeVirtualEquals(99, C);
- assertInvokeInterfaceEquals(99, C, J);
- assertInvokeInterfaceEquals(99, C, K);
- assertInvokeInterfaceEquals(99, C, I);
- assertInvokeInterfaceEquals(99, C, L);
- assertInvokeInterfaceEquals(99, C, M);
- }
-
- /**
- * interface I { int m() default { return 99; } }
- * interface J extends I { int m(); }
- * class C implements J {}
- *
- * TEST: C c = new C(); c.m() throws AME
- */
- public void testReabstract() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", I, AbstractMethod.std());
- Class C = new Class("C", J);
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface I { default int m() { return 88; } }
- * interface J extends I { default int m() { return 99; } }
- * class C implements J {}
- *
- * TEST: C c = new C(); c.m() == 99;
- * TEST: J j = new C(); j.m() == 99;
- * TEST: I i = new C(); i.m() == 99;
- */
- public void testShadow() {
- Interface I = new Interface("I", DefaultMethod.std("88"));
- Interface J = new Interface("J", I, DefaultMethod.std("99"));
- Class C = new Class("C", J);
-
- assertInvokeVirtualEquals(99, C);
- assertInvokeInterfaceEquals(99, C, J);
- assertInvokeInterfaceEquals(99, C, I);
- }
-
- /**
- * interface I { default int m() { return 88; } }
- * interface J extends I { default int m() { return 99; } }
- * class C implements I, J {}
- *
- * TEST: C c = new C(); c.m() == 99;
- * TEST: J j = new C(); j.m() == 99;
- * TEST: I i = new C(); i.m() == 99;
- */
- public void testDisqualified() {
- Interface I = new Interface("I", DefaultMethod.std("88"));
- Interface J = new Interface("J", I, DefaultMethod.std("99"));
- Class C = new Class("C", I, J);
-
- assertInvokeVirtualEquals(99, C);
- assertInvokeInterfaceEquals(99, C, J);
- assertInvokeInterfaceEquals(99, C, I);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * class C implements I {}
- *
- * TEST: C.class.getMethod("m").invoke(new C()) == 99
- */
- public void testReflectCall() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- //workaround accessibility issue when loading C with DirectedClassLoader
- I.addAccessFlag(AccessFlag.PUBLIC);
- Class C = new Class("C", I);
-
- Compiler.Flags[] flags = this.verbose ?
- new Compiler.Flags[] { Compiler.Flags.VERBOSE } :
- new Compiler.Flags[] {};
- Compiler compiler = new Compiler(flags);
- java.lang.Class<?> cls = null;
- try {
- cls = compiler.compileAndLoad(C);
- } catch (ClassNotFoundException e) {
- fail("Could not load class");
- }
-
- java.lang.reflect.Method method = null;
- try {
- method = cls.getMethod(stdMethodName);
- } catch (NoSuchMethodException e) {
- fail("Could not find method in class");
- }
- assertNotNull(method);
-
- Object c = null;
- try {
- c = cls.newInstance();
- } catch (InstantiationException | IllegalAccessException e) {
- fail("Could not create instance of class");
- }
- assertNotNull(c);
-
- Integer res = null;
- try {
- res = (Integer)method.invoke(c);
- } catch (IllegalAccessException |
- java.lang.reflect.InvocationTargetException e) {
- fail("Could not invoke default instance method");
- }
- assertNotNull(res);
-
- assertEquals(res.intValue(), 99);
-
- compiler.cleanup();
- }
-
-
- /**
- * interface J { default int m() { return 88; } }
- * interface I extends J { default int m() { return J.super.m(); } }
- * class C implements I {}
- *
- * TEST: C c = new C(); c.m() == 88;
- * TEST: I i = new C(); i.m() == 88;
- */
- public void testSuperBasic() {
- // debugTest();
-
- Interface J = new Interface("J", DefaultMethod.std("88"));
- Interface I = new Interface("I", J, new DefaultMethod(
- "int", stdMethodName, "return J.super.m();"));
- I.addCompilationDependency(J.findMethod(stdMethodName));
- Class C = new Class("C", I);
-
- assertInvokeVirtualEquals(88, C);
- assertInvokeInterfaceEquals(88, C, I);
- }
-
- /**
- * interface K { int m() default { return 99; } }
- * interface L { int m() default { return 101; } }
- * interface J extends K, L {}
- * interface I extends J, K { int m() default { J.super.m(); } }
- * class C implements I {}
- *
- * TEST: C c = new C(); c.m() throws AME
- * TODO: add case for K k = new C(); k.m() throws AME
- */
- public void testSuperConflict() {
- // debugTest();
-
- Interface K = new Interface("K", DefaultMethod.std("99"));
- Interface L = new Interface("L", DefaultMethod.std("101"));
- Interface J = new Interface("J", K, L);
- Interface I = new Interface("I", J, K, new DefaultMethod(
- "int", stdMethodName, "return J.super.m();"));
- Interface Jstub = new Interface("J", DefaultMethod.std("-1"));
- I.addCompilationDependency(Jstub);
- I.addCompilationDependency(Jstub.findMethod(stdMethodName));
- Class C = new Class("C", I);
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface I { default int m() { return 99; } }
- * interface J extends I { default int m() { return 55; } }
- * class C implements I, J { public int m() { return I.super.m(); } }
- *
- * TEST: C c = new C(); c.m() throws AME
- * TODO: add case for J j = new C(); j.m() throws AME
- */
- public void testSuperDisqual() {
- Interface I = new Interface("I", DefaultMethod.std("99"));
- Interface J = new Interface("J", I, DefaultMethod.std("55"));
- Class C = new Class("C", I, J,
- new ConcreteMethod("int", stdMethodName, "return I.super.m();",
- AccessFlag.PUBLIC));
- C.addCompilationDependency(I.findMethod(stdMethodName));
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface J { int m(); }
- * interface I extends J { default int m() { return J.super.m(); } }
- * class C implements I {}
- *
- * TEST: C c = new C(); c.m() throws AME
- * TODO: add case for I i = new C(); i.m() throws AME
- */
- public void testSuperNull() {
- Interface J = new Interface("J", AbstractMethod.std());
- Interface I = new Interface("I", J, new DefaultMethod(
- "int", stdMethodName, "return J.super.m();"));
- Interface Jstub = new Interface("J", DefaultMethod.std("99"));
- I.addCompilationDependency(Jstub);
- I.addCompilationDependency(Jstub.findMethod(stdMethodName));
- Class C = new Class("C", I);
-
- assertThrows(AbstractMethodError.class, C);
- }
-
- /**
- * interface J<T> { default int m(T t) { return 88; } }
- * interface I extends J<String> {
- * int m(String s) default { return J.super.m(); }
- * }
- * class C implements I {}
- *
- * TEST: I i = new C(); i.m("") == 88;
- */
- public void testSuperGeneric() {
- Interface J = new Interface("J", new TypeParameter("T"),
- new DefaultMethod("int", stdMethodName, "return 88;",
- new MethodParameter("T", "t")));
- Interface I = new Interface("I", J.with("String"),
- new DefaultMethod("int", stdMethodName, "return J.super.m(s);",
- new MethodParameter("String", "s")));
- I.addCompilationDependency(J.findMethod(stdMethodName));
- Class C = new Class("C", I);
-
- AbstractMethod pm = new AbstractMethod("int", stdMethodName,
- new MethodParameter("String", "s"));
-
- assertInvokeInterfaceEquals(
- new Integer(88), C, new Extends(I), pm, "\"\"");
- }
-
- /**
- * interface I<T> { int m(T t) default { return 44; } }
- * interface J extends I<String> { int m(String s) default { return 55; } }
- * class C implements I<String>, J {
- * public int m(String s) { return I.super.m(s); }
- * }
- *
- * TEST: C c = new C(); c.m("string") throws AME
- */
- public void testSuperGenericDisqual() {
- MethodParameter t = new MethodParameter("T", "t");
- MethodParameter s = new MethodParameter("String", "s");
-
- Interface I = new Interface("I", new TypeParameter("T"),
- new DefaultMethod("int", stdMethodName, "return 44;", t));
- Interface J = new Interface("J", I.with("String"),
- new DefaultMethod("int", stdMethodName, "return 55;", s));
- Class C = new Class("C", I.with("String"), J,
- new ConcreteMethod("int", stdMethodName,
- "return I.super.m(s);", AccessFlag.PUBLIC, s));
- C.addCompilationDependency(I.findMethod(stdMethodName));
-
- assertThrows(AbstractMethodError.class, C,
- new ConcreteMethod(
- "int", stdMethodName, "return -1;", AccessFlag.PUBLIC, s),
- "-1", "\"string\"");
- }
-
- /**
- * interface I { default Integer m() { return new Integer(88); } }
- * class C { int m() { return 99; } }
- * class D extends C implements I {}
- * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger;
- * TEST: S s = new S(); s.foo() == new Integer(88)
- */
- public void testNoCovarNoBridge() {
- Interface I = new Interface("I", new DefaultMethod(
- "Integer", "m", "return new Integer(88);"));
- Class C = new Class("C", new ConcreteMethod(
- "int", "m", "return 99;", AccessFlag.PUBLIC));
- Class D = new Class("D", I, C);
-
- ConcreteMethod DstubMethod = new ConcreteMethod(
- "Integer", "m", "return null;", AccessFlag.PUBLIC);
- Class Dstub = new Class("D", DstubMethod);
-
- ConcreteMethod toCall = new ConcreteMethod(
- "Object", "foo", "return (new D()).m();", AccessFlag.PUBLIC);
- Class S = new Class("S", D, toCall);
- S.addCompilationDependency(Dstub);
- S.addCompilationDependency(DstubMethod);
-
- assertInvokeVirtualEquals(new Integer(88), S, toCall, "null");
- }
-
- /**
- * interface J { int m(); }
- * interface I extends J { default int m() { return 99; } }
- * class B implements J {}
- * class C extends B implements I {}
- * TEST: C c = new C(); c.m() == 99
- *
- * The point of this test is that B does not get default method analysis,
- * and C does not generate any new miranda methods in the vtable.
- * It verifies that default method analysis occurs when mirandas have been
- * inherited and the supertypes don't have any overpass methods.
- */
- public void testNoNewMiranda() {
- Interface J = new Interface("J", AbstractMethod.std());
- Interface I = new Interface("I", J, DefaultMethod.std("99"));
- Class B = new Class("B", J);
- Class C = new Class("C", B, I);
- assertInvokeVirtualEquals(99, C);
- }
-
- public void testStrictfpDefault() {
- try {
- java.lang.Class.forName("vm.StrictfpDefault");
- } catch (Exception e) {
- fail("Could not load class", e);
- }
- }
-}
diff --git a/test/lib/testlibrary/jdk/testlibrary/Asserts.java b/test/lib/testlibrary/jdk/testlibrary/Asserts.java
new file mode 100644
index 0000000..d5e1361
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/Asserts.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+/**
+ * Asserts that can be used for verifying assumptions in tests.
+ *
+ * An assertion will throw a {@link RuntimeException} if the assertion isn't
+ * valid. All the asserts can be imported into a test by using a static
+ * import:
+ *
+ * <pre>
+ * {@code
+ * import static com.oracle.java.testlibrary.Asserts.*;
+ * }
+ *
+ * Always provide a message describing the assumption if the line number of the
+ * failing assertion isn't enough to understand why the assumption failed. For
+ * example, if the assertion is in a loop or in a method that is called
+ * multiple times, then the line number won't provide enough context to
+ * understand the failure.
+ * </pre>
+ */
+public class Asserts {
+
+ /**
+ * Shorthand for {@link #assertLessThan(T, T)}.
+ *
+ * @see #assertLessThan(T, T)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs) {
+ assertLessThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThan(T, T, String)}.
+ *
+ * @see #assertLessThan(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs, String msg) {
+ assertLessThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThan(T, T, String)} with a default message.
+ *
+ * @see #assertLessThan(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThan(T lhs, T rhs) {
+ String msg = "Expected that " + format(lhs) + " < " + format(rhs);
+ assertLessThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static <T extends Comparable<T>>void assertLessThan(T lhs, T rhs, String msg) {
+ assertTrue(compare(lhs, rhs, msg) < 0, msg);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(T, T)}.
+ *
+ * @see #assertLessThanOrEqual(T, T)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs) {
+ assertLessThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(T, T, String)}.
+ *
+ * @see #assertLessThanOrEqual(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs, String msg) {
+ assertLessThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThanOrEqual(T, T, String)} with a default message.
+ *
+ * @see #assertLessThanOrEqual(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs) {
+ String msg = "Expected that " + format(lhs) + " <= " + format(rhs);
+ assertLessThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than or equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs, String msg) {
+ assertTrue(compare(lhs, rhs, msg) <= 0, msg);
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(T, T)}.
+ *
+ * @see #assertEquals(T, T)
+ */
+ public static void assertEQ(Object lhs, Object rhs) {
+ assertEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(T, T, String)}.
+ *
+ * @see #assertEquals(T, T, String)
+ */
+ public static void assertEQ(Object lhs, Object rhs, String msg) {
+ assertEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertEquals(T, T, String)} with a default message.
+ *
+ * @see #assertEquals(T, T, String)
+ */
+ public static void assertEquals(Object lhs, Object rhs) {
+ String msg = "Expected " + format(lhs) + " to equal " + format(rhs);
+ assertEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertEquals(Object lhs, Object rhs, String msg) {
+ if (lhs == null) {
+ if (rhs != null) {
+ error(msg);
+ }
+ } else {
+ assertTrue(lhs.equals(rhs), msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(T, T)}.
+ *
+ * @see #assertGreaterThanOrEqual(T, T)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs) {
+ assertGreaterThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(T, T, String)}.
+ *
+ * @see #assertGreaterThanOrEqual(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs, String msg) {
+ assertGreaterThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThanOrEqual(T, T, String)} with a default message.
+ *
+ * @see #assertGreaterThanOrEqual(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs) {
+ String msg = "Expected that " + format(lhs) + " >= " + format(rhs);
+ assertGreaterThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than or equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs, String msg) {
+ assertTrue(compare(lhs, rhs, msg) >= 0, msg);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(T, T)}.
+ *
+ * @see #assertGreaterThan(T, T)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs) {
+ assertGreaterThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(T, T, String)}.
+ *
+ * @see #assertGreaterThan(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs, String msg) {
+ assertGreaterThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThan(T, T, String)} with a default message.
+ *
+ * @see #assertGreaterThan(T, T, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs) {
+ String msg = "Expected that " + format(lhs) + " > " + format(rhs);
+ assertGreaterThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs, String msg) {
+ assertTrue(compare(lhs, rhs, msg) > 0, msg);
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(T, T)}.
+ *
+ * @see #assertNotEquals(T, T)
+ */
+ public static void assertNE(Object lhs, Object rhs) {
+ assertNotEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(T, T, String)}.
+ *
+ * @see #assertNotEquals(T, T, String)
+ */
+ public static void assertNE(Object lhs, Object rhs, String msg) {
+ assertNotEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotEquals(T, T, String)} with a default message.
+ *
+ * @see #assertNotEquals(T, T, String)
+ */
+ public static void assertNotEquals(Object lhs, Object rhs) {
+ String msg = "Expected " + format(lhs) + " to not equal " + format(rhs);
+ assertNotEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Asserts that {@code lhs} is not equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertNotEquals(Object lhs, Object rhs, String msg) {
+ if (lhs == null) {
+ if (rhs == null) {
+ error(msg);
+ }
+ } else {
+ assertFalse(lhs.equals(rhs), msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertNull(Object, String)} with a default message.
+ *
+ * @see #assertNull(Object, String)
+ */
+ public static void assertNull(Object o) {
+ assertNull(o, "Expected " + format(o) + " to be null");
+ }
+
+ /**
+ * Asserts that {@code o} is null.
+ *
+ * @param o The reference assumed to be null.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertNull(Object o, String msg) {
+ assertEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotNull(Object, String)} with a default message.
+ *
+ * @see #assertNotNull(Object, String)
+ */
+ public static void assertNotNull(Object o) {
+ assertNotNull(o, "Expected non null reference");
+ }
+
+ /**
+ * Asserts that {@code o} is <i>not</i> null.
+ *
+ * @param o The reference assumed <i>not</i> to be null,
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertNotNull(Object o, String msg) {
+ assertNotEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertFalse(boolean, String)} with a default message.
+ *
+ * @see #assertFalse(boolean, String)
+ */
+ public static void assertFalse(boolean value) {
+ assertFalse(value, "Expected value to be false");
+ }
+
+ /**
+ * Asserts that {@code value} is {@code false}.
+ *
+ * @param value The value assumed to be false.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertFalse(boolean value, String msg) {
+ assertTrue(!value, msg);
+ }
+
+ /**
+ * Calls {@link #assertTrue(boolean, String)} with a default message.
+ *
+ * @see #assertTrue(boolean, String)
+ */
+ public static void assertTrue(boolean value) {
+ assertTrue(value, "Expected value to be true");
+ }
+
+ /**
+ * Asserts that {@code value} is {@code true}.
+ *
+ * @param value The value assumed to be true.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if the assertion isn't valid.
+ */
+ public static void assertTrue(boolean value, String msg) {
+ if (!value) {
+ error(msg);
+ }
+ }
+
+ private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) {
+ assertNotNull(lhs, msg);
+ assertNotNull(rhs, msg);
+ return lhs.compareTo(rhs);
+ }
+
+ private static String format(Object o) {
+ return o == null? "null" : o.toString();
+ }
+
+ private static void error(String msg) {
+ throw new RuntimeException(msg);
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java b/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java
new file mode 100644
index 0000000..69839d8
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public final class JDKToolFinder {
+
+ private JDKToolFinder() {
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite)
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getJDKTool(String tool) {
+
+ // First try to find the executable in test.jdk
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+
+ }
+
+ // Now see if it's available in compile.jdk
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Failed to find " + tool +
+ ", looked in test.jdk (" + System.getProperty("test.jdk") +
+ ") and compile.jdk (" + System.getProperty("compile.jdk") + ")");
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code compile.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getCompileJDKTool(String tool) {
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getTestJDKTool(String tool) {
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String getTool(String tool, String property) throws FileNotFoundException {
+ String jdkPath = System.getProperty(property);
+
+ if (jdkPath == null) {
+ throw new RuntimeException(
+ "System property '" + property + "' not set. This property is normally set by jtreg. "
+ + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'.");
+ }
+
+ Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : ""));
+
+ Path jdkTool = Paths.get(jdkPath, toolName.toString());
+ if (!jdkTool.toFile().exists()) {
+ throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath());
+ }
+
+ return jdkTool.toAbsolutePath().toString();
+ }
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java b/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java
new file mode 100644
index 0000000..fcee222
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A utility for constructing command lines for starting JDK tool processes.
+ *
+ * The JDKToolLauncher can in particular be combined with a
+ * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
+ * code run {@code jmap -heap} against a process with GC logging turned on for
+ * the {@code jmap} process:
+ *
+ * <pre>
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ * .addVMArg("-XX:+PrintGC");
+ * .addVMArg("-XX:+PrintGCDetails")
+ * .addToolArg("-heap")
+ * .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * </pre>
+ */
+public class JDKToolLauncher {
+ private final String executable;
+ private final List<String> vmArgs = new ArrayList<String>();
+ private final List<String> toolArgs = new ArrayList<String>();
+
+ private JDKToolLauncher(String tool, boolean useCompilerJDK) {
+ if (useCompilerJDK) {
+ executable = JDKToolFinder.getJDKTool(tool);
+ } else {
+ executable = JDKToolFinder.getTestJDKTool(tool);
+ }
+ vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool. Using tools path
+ * from the compiler JDK.
+ *
+ * @param tool
+ * The name of the tool
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher create(String tool) {
+ return new JDKToolLauncher(tool, true);
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool in the Tested JDK.
+ *
+ * @param tool
+ * The name of the tool
+ *
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher createUsingTestJDK(String tool) {
+ return new JDKToolLauncher(tool, false);
+ }
+
+ /**
+ * Adds an argument to the JVM running the tool.
+ *
+ * The JVM arguments are passed to the underlying JVM running the tool.
+ * Arguments will automatically be prepended with "-J".
+ *
+ * Any platform specific arguments required for running the tool are
+ * automatically added.
+ *
+ *
+ * @param arg
+ * The argument to VM running the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addVMArg(String arg) {
+ vmArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Adds an argument to the tool.
+ *
+ * @param arg
+ * The argument to the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addToolArg(String arg) {
+ toolArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Returns the command that can be used for running the tool.
+ *
+ * @return An array whose elements are the arguments of the command.
+ */
+ public String[] getCommand() {
+ List<String> command = new ArrayList<String>();
+ command.add(executable);
+ // Add -J in front of all vmArgs
+ for (String arg : vmArgs) {
+ command.add("-J" + arg);
+ }
+ command.addAll(toolArgs);
+ return command.toArray(new String[command.size()]);
+ }
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/Platform.java b/test/lib/testlibrary/jdk/testlibrary/Platform.java
new file mode 100644
index 0000000..6b92c28
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/Platform.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+public class Platform {
+ private static final String osName = System.getProperty("os.name");
+ private static final String dataModel = System.getProperty("sun.arch.data.model");
+ private static final String vmVersion = System.getProperty("java.vm.version");
+ private static final String osArch = System.getProperty("os.arch");
+
+ public static boolean is32bit() {
+ return dataModel.equals("32");
+ }
+
+ public static boolean is64bit() {
+ return dataModel.equals("64");
+ }
+
+ public static boolean isSolaris() {
+ return isOs("sunos");
+ }
+
+ public static boolean isWindows() {
+ return isOs("win");
+ }
+
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ private static boolean isOs(String osname) {
+ return osName.toLowerCase().startsWith(osname.toLowerCase());
+ }
+
+ public static String getOsName() {
+ return osName;
+ }
+
+ public static boolean isDebugBuild() {
+ return vmVersion.toLowerCase().contains("debug");
+ }
+
+ public static String getVMVersion() {
+ return vmVersion;
+ }
+
+ // Returns true for sparc and sparcv9.
+ public static boolean isSparc() {
+ return isArch("sparc");
+ }
+
+ public static boolean isARM() {
+ return isArch("arm");
+ }
+
+ public static boolean isPPC() {
+ return isArch("ppc");
+ }
+
+ public static boolean isX86() {
+ // On Linux it's 'i386', Windows 'x86'
+ return (isArch("i386") || isArch("x86"));
+ }
+
+ public static boolean isX64() {
+ // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64'
+ return (isArch("amd64") || isArch("x86_64"));
+ }
+
+ private static boolean isArch(String archname) {
+ return osArch.toLowerCase().startsWith(archname.toLowerCase());
+ }
+
+ public static String getOsArch() {
+ return osArch;
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java b/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java
new file mode 100644
index 0000000..32e324e
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+import static jdk.testlibrary.Asserts.assertNotEquals;
+import static jdk.testlibrary.Asserts.assertTrue;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * The helper class for starting and stopping {@link Process} in a separate thread.
+ */
+public class ProcessThread extends TestThread {
+
+ /**
+ * Creates a new {@code ProcessThread} object.
+ *
+ * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
+ */
+ public ProcessThread(List<String> cmd) {
+ super(new ProcessRunnable(cmd));
+ }
+
+ /**
+ * Creates a new {@code ProcessThread} object.
+ *
+ * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
+ */
+ public ProcessThread(String... cmd) {
+ super(new ProcessRunnable(cmd));
+ }
+
+ /**
+ * Creates a new {@code ProcessThread} object.
+ *
+ * @param threadName The name of thread
+ * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
+ */
+ public ProcessThread(String threadName, List<String> cmd) {
+ super(new ProcessRunnable(cmd), threadName);
+ }
+
+ /**
+ * Creates a new {@code ProcessThread} object.
+ *
+ * @param threadName The name of thread
+ * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
+ */
+ public ProcessThread(String threadName, String... cmd) {
+ super(new ProcessRunnable(cmd), threadName);
+ }
+
+ /**
+ * Stops {@link Process} started by {@code ProcessRunnable}.
+ *
+ * @throws InterruptedException
+ */
+ public void stopProcess() throws InterruptedException {
+ ((ProcessRunnable) getRunnable()).stopProcess();
+ }
+
+ /**
+ * {@link Runnable} interface for starting and stopping {@link Process}.
+ */
+ static class ProcessRunnable extends XRun {
+
+ private final ProcessBuilder processBuilder;
+ private final CountDownLatch latch;
+ private volatile Process process;
+
+ /**
+ * Creates a new {@code ProcessRunnable} object.
+ *
+ * @param cmd The list of program and its arguments to to pass to {@link ProcessBuilder}
+ */
+ public ProcessRunnable(List<String> cmd) {
+ super();
+ this.processBuilder = new ProcessBuilder(cmd);
+ this.latch = new CountDownLatch(1);
+ }
+
+ /**
+ * Creates a new {@code ProcessRunnable} object.
+ *
+ * @param cmd The string array of program and its arguments to to pass to {@link ProcessBuilder}
+ */
+ public ProcessRunnable(String... cmd) {
+ super();
+ this.processBuilder = new ProcessBuilder(cmd);
+ this.latch = new CountDownLatch(1);
+ }
+
+ /**
+ * Starts the process in {@code ProcessThread}.
+ * All exceptions which occurs here will be caught and stored in {@code ProcessThread}.
+ *
+ * see {@link XRun}
+ */
+ @Override
+ public void xrun() throws Throwable {
+ this.process = processBuilder.start();
+ // Release when process is started
+ latch.countDown();
+
+ // Will block...
+ OutputAnalyzer output = new OutputAnalyzer(this.process);
+
+ assertTrue(output.getOutput().isEmpty(), "Should get an empty output, got: "
+ + Utils.NEW_LINE + output.getOutput());
+ assertNotEquals(output.getExitValue(), 0,
+ "Process exited with unexpected exit code");
+ }
+
+ /**
+ * Stops the process.
+ *
+ * @throws InterruptedException
+ */
+ public void stopProcess() throws InterruptedException {
+ // Wait until process is started
+ latch.await();
+ if (this.process != null) {
+ this.process.destroy();
+ }
+ }
+
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
index 16783ae..29b4e38 100644
--- a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
+++ b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
@@ -25,24 +25,127 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
import sun.management.VMManagement;
public final class ProcessTools {
+ private static final class LineForwarder extends StreamPumper.LinePump {
+ private final PrintStream ps;
+ private final String prefix;
+ LineForwarder(String prefix, PrintStream os) {
+ this.ps = os;
+ this.prefix = prefix;
+ }
+ @Override
+ protected void processLine(String line) {
+ ps.println("[" + prefix + "] " + line);
+ }
+ }
private ProcessTools() {
}
/**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @return Returns the initialized process
+ * @throws IOException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder)
+ throws IOException {
+ Process p = null;
+ try {
+ p = startProcess(name, processBuilder, null, -1, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException | TimeoutException e) {
+ // can't ever happen
+ }
+ return p;
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @param timeout The timeout for the warmup waiting
+ * @param unit The timeout {@linkplain TimeUnit}
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Predicate<String> linePredicate,
+ long timeout,
+ TimeUnit unit)
+ throws IOException, InterruptedException, TimeoutException {
+ Process p = processBuilder.start();
+ StreamPumper stdout = new StreamPumper(p.getInputStream());
+ StreamPumper stderr = new StreamPumper(p.getErrorStream());
+
+ stdout.addPump(new LineForwarder(name, System.out));
+ stderr.addPump(new LineForwarder(name, System.err));
+ final Phaser phs = new Phaser(1);
+ if (linePredicate != null) {
+ stdout.addPump(new StreamPumper.LinePump() {
+ @Override
+ protected void processLine(String line) {
+ if (linePredicate.test(line)) {
+ if (phs.getRegisteredParties() > 0) {
+ phs.arriveAndDeregister();
+ }
+ }
+ }
+ });
+ }
+ Future<Void> stdoutTask = stdout.process();
+ Future<Void> stderrTask = stderr.process();
+
+ try {
+ if (timeout > -1) {
+ phs.awaitAdvanceInterruptibly(0, timeout, unit);
+ }
+ } catch (TimeoutException | InterruptedException e) {
+ stdoutTask.cancel(true);
+ stderrTask.cancel(true);
+ throw e;
+ }
+
+ return p;
+ }
+
+ /**
* Pumps stdout and stderr from running the process into a String.
*
- * @param processHandler
+ * @param processBuilder
* ProcessHandler to run.
* @return Output from process.
* @throws IOException
@@ -69,22 +172,19 @@
stdoutBuffer);
StreamPumper errPumper = new StreamPumper(process.getErrorStream(),
stderrBuffer);
- Thread outPumperThread = new Thread(outPumper);
- Thread errPumperThread = new Thread(errPumper);
- outPumperThread.setDaemon(true);
- errPumperThread.setDaemon(true);
-
- outPumperThread.start();
- errPumperThread.start();
+ Future<Void> outTask = outPumper.process();
+ Future<Void> errTask = errPumper.process();
try {
process.waitFor();
- outPumperThread.join();
- errPumperThread.join();
+ outTask.get();
+ errTask.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
+ } catch (ExecutionException e) {
+ throw new IOException(e);
}
return new OutputBuffer(stdoutBuffer.toString(),
diff --git a/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java b/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java
index 60adca4..224dcb2 100644
--- a/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java
+++ b/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java
@@ -23,16 +23,65 @@
package jdk.testlibrary;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicBoolean;
public final class StreamPumper implements Runnable {
private static final int BUF_SIZE = 256;
- private final OutputStream out;
+ /**
+ * Pump will be called by the StreamPumper to process the incoming data
+ */
+ abstract public static class Pump {
+ abstract void register(StreamPumper d);
+ }
+
+ /**
+ * OutputStream -> Pump adapter
+ */
+ final public static class StreamPump extends Pump {
+ private final OutputStream out;
+ public StreamPump(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ void register(StreamPumper sp) {
+ sp.addOutputStream(out);
+ }
+ }
+
+ /**
+ * Used to process the incoming data line-by-line
+ */
+ abstract public static class LinePump extends Pump {
+ @Override
+ final void register(StreamPumper sp) {
+ sp.addLineProcessor(this);
+ }
+
+ abstract protected void processLine(String line);
+ }
+
private final InputStream in;
+ private final Set<OutputStream> outStreams = new HashSet<>();
+ private final Set<LinePump> linePumps = new HashSet<>();
+
+ private final AtomicBoolean processing = new AtomicBoolean(false);
+ private final FutureTask<Void> processingTask = new FutureTask(this, null);
+
+ public StreamPumper(InputStream in) {
+ this.in = in;
+ }
/**
* Create a StreamPumper that reads from in and writes to out.
@@ -43,8 +92,8 @@
* The stream to write to.
*/
public StreamPumper(InputStream in, OutputStream out) {
- this.in = in;
- this.out = out;
+ this(in);
+ this.addOutputStream(out);
}
/**
@@ -54,25 +103,97 @@
*/
@Override
public void run() {
- int length;
- InputStream localIn = in;
- OutputStream localOut = out;
- byte[] buffer = new byte[BUF_SIZE];
+ try (BufferedInputStream is = new BufferedInputStream(in)) {
+ ByteArrayOutputStream lineBos = new ByteArrayOutputStream();
+ byte[] buf = new byte[BUF_SIZE];
+ int len = 0;
+ int linelen = 0;
- try {
- while ((length = localIn.read(buffer)) > 0 && !Thread.interrupted()) {
- localOut.write(buffer, 0, length);
+ while ((len = is.read(buf)) > 0 && !Thread.interrupted()) {
+ for(OutputStream out : outStreams) {
+ out.write(buf, 0, len);
+ }
+ if (!linePumps.isEmpty()) {
+ int i = 0;
+ int lastcrlf = -1;
+ while (i < len) {
+ if (buf[i] == '\n' || buf[i] == '\r') {
+ int bufLinelen = i - lastcrlf - 1;
+ if (bufLinelen > 0) {
+ lineBos.write(buf, lastcrlf + 1, bufLinelen);
+ }
+ linelen += bufLinelen;
+
+ if (linelen > 0) {
+ lineBos.flush();
+ final String line = lineBos.toString();
+ linePumps.stream().forEach((lp) -> {
+ lp.processLine(line);
+ });
+ lineBos.reset();
+ linelen = 0;
+ }
+ lastcrlf = i;
+ }
+
+ i++;
+ }
+ if (lastcrlf == -1) {
+ lineBos.write(buf, 0, len);
+ linelen += len;
+ } else if (lastcrlf < len - 1) {
+ lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1);
+ linelen += len - lastcrlf - 1;
+ }
+ }
}
+
} catch (IOException e) {
- // Just abort if something like this happens.
e.printStackTrace();
} finally {
- try {
- localOut.flush();
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
+ for(OutputStream out : outStreams) {
+ try {
+ out.flush();
+ } catch (IOException e) {}
}
+ try {
+ in.close();
+ } catch (IOException e) {}
}
}
+
+ final void addOutputStream(OutputStream out) {
+ outStreams.add(out);
+ }
+
+ final void addLineProcessor(LinePump lp) {
+ linePumps.add(lp);
+ }
+
+ final public StreamPumper addPump(Pump ... pump) {
+ if (processing.get()) {
+ throw new IllegalStateException("Can not modify pumper while " +
+ "processing is in progress");
+ }
+ for(Pump p : pump) {
+ p.register(this);
+ }
+ return this;
+ }
+
+ final public Future<Void> process() {
+ if (!processing.compareAndSet(false, true)) {
+ throw new IllegalStateException("Can not re-run the processing");
+ }
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ processingTask.run();
+ }
+ });
+ t.setDaemon(true);
+ t.start();
+
+ return processingTask;
+ }
}
diff --git a/test/lib/testlibrary/jdk/testlibrary/TestThread.java b/test/lib/testlibrary/jdk/testlibrary/TestThread.java
new file mode 100644
index 0000000..26b0604
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/TestThread.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Thread which catches exceptions thrown during the execution
+ * and stores them for later analysis.
+ *
+ * <pre>
+ * {@code
+ * TestThread thread = new TestThread(new XRun() {
+ * public void run() {
+ * // do something
+ * }
+ * });
+ * thread.start();
+ * // do something
+ * Throwable uncaught = thread.getUncaught();
+ * }
+ * </pre>
+ */
+public class TestThread extends Thread {
+
+ private final Runnable runnable;
+ private volatile Throwable uncaught;
+
+ /**
+ * Returns {@link Runnable} the thread has been created with.
+ *
+ * @return The object whose {@code run} method is called
+ */
+ public Runnable getRunnable() {
+ return runnable;
+ }
+
+ /**
+ * Creates a new {@code TestThread} object.
+ *
+ * @param target The object whose {@code run} method is called
+ * @param name The thread name
+ */
+ public TestThread(Runnable target, String name) {
+ super(target, name);
+ this.runnable = target;
+ }
+
+ /**
+ * Creates a new {@code TestThread} object.
+ *
+ * @param target The object whose {@code run} method is called
+ */
+ public TestThread(Runnable target) {
+ super(target);
+ this.runnable = target;
+ }
+
+ /**
+ * Creates a new {@code TestThread} object.
+ *
+ * @param group The thread group
+ * @param target The object whose {@code run} method is called
+ * @param name The thread name
+ * @param stackSize Stack size
+ */
+ public TestThread(ThreadGroup group, Runnable target, String name,
+ long stackSize) {
+ super(group, target, name, stackSize);
+ this.runnable = target;
+ }
+
+ /**
+ * Creates a new {@code TestThread} object.
+ *
+ * @param group The thread group
+ * @param target The object whose {@code run} method is called
+ * @param name The thread name
+ */
+ public TestThread(ThreadGroup group, Runnable target, String name) {
+ super(group, target, name);
+ this.runnable = target;
+ }
+
+ /**
+ * Creates a new {@code TestThread} object.
+ *
+ * @param group The thread group
+ * @param target The object whose {@code run} method is called
+ */
+ public TestThread(ThreadGroup group, Runnable target) {
+ super(group, target);
+ this.runnable = target;
+ }
+
+ /**
+ * The thread executor.
+ */
+ @Override
+ public void run() {
+ try {
+ super.run();
+ } catch (Throwable t) {
+ uncaught = t;
+ }
+ }
+
+ /**
+ * Returns exception caught during the execution.
+ *
+ * @return {@link Throwable}
+ */
+ public Throwable getUncaught() {
+ return uncaught;
+ }
+
+ /**
+ * Waits for {@link TestThread} to die
+ * and throws exception caught during the execution.
+ *
+ * @throws InterruptedException
+ * @throws Throwable
+ */
+ public void joinAndThrow() throws InterruptedException, Throwable {
+ join();
+ if (uncaught != null) {
+ throw uncaught;
+ }
+ }
+
+ /**
+ * Waits during {@code timeout} for {@link TestThread} to die
+ * and throws exception caught during the execution.
+ *
+ * @param timeout The time to wait in milliseconds
+ * @throws InterruptedException
+ * @throws Throwable
+ */
+ public void joinAndThrow(long timeout) throws InterruptedException,
+ Throwable {
+ join(timeout);
+ if (isAlive()) {
+ throw new TimeoutException();
+ }
+ if (uncaught != null) {
+ throw uncaught;
+ }
+ }
+
+ /**
+ * Waits for {@link TestThread} to die
+ * and returns exception caught during the execution.
+ *
+ * @return Exception caught during the execution
+ * @throws InterruptedException
+ */
+ public Throwable joinAndReturn() throws InterruptedException {
+ join();
+ if (uncaught != null) {
+ return uncaught;
+ }
+ return null;
+ }
+
+ /**
+ * Waits during {@code timeout} for {@link TestThread} to die
+ * and returns exception caught during the execution.
+ *
+ * @param timeout The time to wait in milliseconds
+ * @return Exception caught during the execution
+ * @throws InterruptedException
+ */
+ public Throwable joinAndReturn(long timeout) throws InterruptedException {
+ join(timeout);
+ if (isAlive()) {
+ return new TimeoutException();
+ }
+ if (uncaught != null) {
+ return uncaught;
+ }
+ return null;
+ }
+
+ /**
+ * Waits until {@link TestThread} is in the certain {@link State}
+ * and blocking on {@code object}.
+ *
+ * @param state The thread state
+ * @param object The object to block on
+ */
+ public void waitUntilBlockingOnObject(Thread.State state, Object object) {
+ String want = object == null ? null : object.getClass().getName() + '@'
+ + Integer.toHexString(System.identityHashCode(object));
+ ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
+ while (isAlive()) {
+ ThreadInfo ti = tmx.getThreadInfo(getId());
+ if (ti.getThreadState() == state
+ && (want == null || want.equals(ti.getLockName()))) {
+ return;
+ }
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /**
+ * Waits until {@link TestThread} is in native.
+ */
+ public void waitUntilInNative() {
+ ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
+ while (isAlive()) {
+ ThreadInfo ti = tmx.getThreadInfo(getId());
+ if (ti.isInNative()) {
+ return;
+ }
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/Utils.java b/test/lib/testlibrary/jdk/testlibrary/Utils.java
new file mode 100644
index 0000000..f8da7cf
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/Utils.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+import static jdk.testlibrary.Asserts.assertTrue;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common library for various test helper functions.
+ */
+public final class Utils {
+
+ /**
+ * Returns the sequence used by operating system to separate lines.
+ */
+ public static final String NEW_LINE = System.getProperty("line.separator");
+
+ /**
+ * Returns the value of 'test.vm.opts'system property.
+ */
+ public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "");
+
+
+ private Utils() {
+ // Private constructor to prevent class instantiation
+ }
+
+ /**
+ * Returns the list of VM options.
+ *
+ * @return List of VM options
+ */
+ public static List<String> getVmOptions() {
+ return getVmOptions(false);
+ }
+
+ /**
+ * Returns the list of VM options with -J prefix.
+ *
+ * @return The list of VM options with -J prefix
+ */
+ public static List<String> getForwardVmOptions() {
+ return getVmOptions(true);
+ }
+
+ private static List<String> getVmOptions(boolean forward) {
+ List<String> optionsList = new ArrayList<>();
+ String options = VM_OPTIONS.trim();
+ if (!options.isEmpty()) {
+ options = options.replaceAll("\\s+", " ");
+ for (String option : options.split(" ")) {
+ if (forward) {
+ optionsList.add("-J" + option);
+ } else {
+ optionsList.add(option);
+ }
+ }
+ }
+
+ return optionsList;
+ }
+
+ /**
+ * Returns the free port on the local host.
+ * The function will spin until a valid port number is found.
+ *
+ * @return The port number
+ * @throws InterruptedException if any thread has interrupted the current thread
+ * @throws IOException if an I/O error occurs when opening the socket
+ */
+ public static int getFreePort() throws InterruptedException, IOException {
+ int port = -1;
+
+ while (port <= 0) {
+ Thread.sleep(100);
+
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(0);
+ port = serverSocket.getLocalPort();
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ return port;
+ }
+
+ /**
+ * Returns the name of the local host.
+ *
+ * @return The host name
+ * @throws UnknownHostException if IP address of a host could not be determined
+ */
+ public static String getHostname() throws UnknownHostException {
+ InetAddress inetAddress = InetAddress.getLocalHost();
+ String hostName = inetAddress.getHostName();
+
+ assertTrue((hostName != null && !hostName.isEmpty()),
+ "Cannot get hostname");
+
+ return hostName;
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/XRun.java b/test/lib/testlibrary/jdk/testlibrary/XRun.java
new file mode 100644
index 0000000..f4e0aad
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/XRun.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 jdk.testlibrary;
+
+/**
+ * This type serves no other purpose than to simply allow automatically running
+ * something in a thread, and have all exceptions propagated to
+ * RuntimeExceptions, which are thrown up to thread, which in turn should
+ * probably be a {@link TestThread} to they are stored.
+ */
+public abstract class XRun implements Runnable {
+
+ /**
+ * Invokes {@code xrun()} and throws all exceptions caught in it
+ * up to the thread.
+ */
+ public final void run() {
+ try {
+ xrun();
+ } catch (Error e) {
+ throw e;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Override this method to implement what to run in the thread.
+ *
+ * @throws Throwable
+ */
+ protected abstract void xrun() throws Throwable;
+}
diff --git a/test/sun/management/jdp/JdpClient.java b/test/sun/management/jdp/JdpClient.java
index 4a23484..992c45e 100644
--- a/test/sun/management/jdp/JdpClient.java
+++ b/test/sun/management/jdp/JdpClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -35,8 +35,10 @@
import java.nio.channels.Selector;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Map;
import sun.management.jdp.JdpException;
import sun.management.jdp.JdpJmxPacket;
+import sun.management.jdp.JdpPacketReader;
public class JdpClient {
@@ -47,6 +49,31 @@
private static int maxPacketCount = 1;
private static int maxEmptyPacketCount = 10;
+ private void get(Map<?,?> map, String key)
+ throws JdpException {
+
+ if (map.get(key) == null) {
+ throw new JdpException("Test failed, packet field " + key + " missed");
+ }
+ }
+
+ private void checkFieldPresence(JdpJmxPacket p)
+ throws IOException, JdpException {
+
+ byte[] b = p.getPacketData();
+
+ JdpPacketReader reader = new JdpPacketReader(b);
+ Map<String,String> pMap = reader.getDiscoveryDataAsMap();
+
+ get(pMap, JdpJmxPacket.UUID_KEY);
+ get(pMap, JdpJmxPacket.MAIN_CLASS_KEY);
+ get(pMap, JdpJmxPacket.JMX_SERVICE_URL_KEY);
+ // get(pMap, JdpJmxPacket.INSTANCE_NAME_KEY);
+ get(pMap, JdpJmxPacket.PROCESS_ID_KEY);
+ get(pMap, JdpJmxPacket.BROADCAST_INTERVAL_KEY);
+ get(pMap, JdpJmxPacket.RMI_HOSTNAME_KEY);
+ }
+
PacketListener(DatagramChannel channel) {
this.channel = channel;
@@ -67,6 +94,8 @@
try {
while (true) {
+ // Use tcpdump -U -w - -s 1400 -c 2 -vv port 7095
+ // to verify that correct packet being sent
sel.selectedKeys().clear();
buf.rewind();
@@ -87,10 +116,10 @@
buf.flip();
byte[] dgramData = new byte[buf.remaining()];
buf.get(dgramData);
-
try {
JdpJmxPacket packet = new JdpJmxPacket(dgramData);
JdpDoSomething.printJdpPacket(packet);
+ checkFieldPresence(packet);
if(++count > maxPacketCount){
break;
}
diff --git a/test/sun/management/jdp/JdpDoSomething.java b/test/sun/management/jdp/JdpDoSomething.java
index ad9366c..56032df 100644
--- a/test/sun/management/jdp/JdpDoSomething.java
+++ b/test/sun/management/jdp/JdpDoSomething.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -32,7 +32,7 @@
public class JdpDoSomething {
private static final String lockFileName = "JdpDoSomething.lck";
- private static final boolean verbose=false;
+ private static final boolean verbose = false;
public static boolean getVerbose(){
return verbose;
@@ -52,6 +52,9 @@
System.out.println("Jmx: " + p.getJmxServiceUrl());
System.out.println("Main: " + p.getMainClass());
System.out.println("InstanceName: " + p.getInstanceName());
+ System.out.println("ProccessId: " + p.getProcessId());
+ System.out.println("BroadcastInterval: " + p.getBroadcastInterval());
+ System.out.println("Rmi Hostname: " + p.getRmiHostname());
System.out.flush();
}
diff --git a/test/sun/management/jdp/JdpTest.sh b/test/sun/management/jdp/JdpTest.sh
index 12698e4..20265f4 100644
--- a/test/sun/management/jdp/JdpTest.sh
+++ b/test/sun/management/jdp/JdpTest.sh
@@ -1,6 +1,6 @@
#!/bin/sh -x
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -56,7 +56,7 @@
if [ ! -d ${_testclasses} ]
then
- mkdir -p ${_testclasses}
+ mkdir -p ${_testclasses}
fi
rm -f ${_testclasses}/*.class
@@ -64,7 +64,7 @@
# Compile testcase
${COMPILEJAVA}/bin/javac -XDignore.symbol.file -d ${_testclasses} \
JdpUnitTest.java \
- JdpDoSomething.java \
+ JdpDoSomething.java \
JdpClient.java
@@ -84,10 +84,10 @@
${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 &
_last_pid=$!
-# wait until VM is actually starts.
+# wait until VM is actually starts.
# please note, if vm doesn't start for some reason
# jtreg kills the test by timeout. Don't file a bug.
- cnt=1
+ cnt=1
while true
do
npid=`_get_pid`
@@ -135,7 +135,6 @@
-Dcom.sun.management.jdp.port=${_port} \
-Dcom.sun.management.jdp.address=${_ip} \
JdpClient
-
}
@@ -156,18 +155,20 @@
_echo "**** Test one ****"
_app_start JdpUnitTest \
- -Dcom.sun.management.jdp.port=${_port} \
- -Dcom.sun.management.jdp.address=${_ip} \
- -Dcom.sun.management.jdp.pause=5
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jdp.pause=5
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -179,21 +180,23 @@
_echo "**** Test two ****"
_app_start JdpDoSomething \
- -Dcom.sun.management.jdp.port=${_port} \
- -Dcom.sun.management.jdp.address=${_ip} \
- -Dcom.sun.management.jdp.pause=5 \
- -Dcom.sun.management.jmxremote.port=${_jmxport} \
- -Dcom.sun.management.jmxremote.authenticate=false \
- -Dcom.sun.management.jmxremote.ssl=false
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
+ -Dcom.sun.management.jdp.pause=5 \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -210,6 +213,7 @@
jdp.port=${_port} \
jdp.address=${_ip} \
jdp.pause=5 \
+ jdp.name=jcmdtest \
jmxremote.port=${_jmxport} \
jmxremote.authenticate=false \
jmxremote.ssl=false
@@ -218,10 +222,10 @@
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -233,19 +237,21 @@
_echo "**** Test four ****"
_app_start JdpDoSomething \
- -Dcom.sun.management.jmxremote.autodiscovery=true \
- -Dcom.sun.management.jmxremote.port=${_jmxport} \
- -Dcom.sun.management.jmxremote.authenticate=false \
- -Dcom.sun.management.jmxremote.ssl=false
+ -Dcom.sun.management.jmxremote.autodiscovery=true \
+ -Dcom.sun.management.jdp.name=testme \
+ -Djava.rmi.server.hostname=localhost \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
+ -Dcom.sun.management.jmxremote.authenticate=false \
+ -Dcom.sun.management.jmxremote.ssl=false
res=`_testme`
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -269,10 +275,10 @@
case "${res}" in
OK*)
- _echo "Passed"
+ _echo "Passed"
;;
*)
- _echo "Failed!"
+ _echo "Failed!"
;;
esac
@@ -300,28 +306,28 @@
for parm in "$@"
do
- case $parm in
- --verbose) _verbose=yes ;;
- --jtreg) _jtreg=yes ;;
- --no-compile) _compile=no ;;
- --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
- *)
- echo "Undefined parameter $parm. Try --help for help"
- exit
- ;;
- esac
+ case $parm in
+ --verbose) _verbose=yes ;;
+ --jtreg) _jtreg=yes ;;
+ --no-compile) _compile=no ;;
+ --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
+ *)
+ echo "Undefined parameter $parm. Try --help for help"
+ exit
+ ;;
+ esac
done
if [ "${_compile}" = "yes" ]
then
- _do_compile
+ _do_compile
fi
if [ "${_jtreg}" = "yes" ]
then
- _testclasses=${TESTCLASSES}
- _testsrc=${TESTSRC}
- _logname="output.txt"
+ _testclasses=${TESTCLASSES}
+ _testsrc=${TESTSRC}
+ _logname="output.txt"
fi
# Make sure _tesclasses is absolute path
diff --git a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
new file mode 100644
index 0000000..3f9e805
--- /dev/null
+++ b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import jdk.testlibrary.JdkFinder;
+import jdk.testlibrary.ProcessTools;
+
+/**
+ * @test
+ * @bug 6434402 8004926
+ * @library /lib/testlibrary
+ * @build TestManager TestApplication CustomLauncherTest
+ * @run main CustomLauncherTest
+ * @author Jaroslav Bachorik
+ */
+public class CustomLauncherTest {
+ private static final String TEST_CLASSES = System.getProperty("test.classes");
+ private static final String TEST_JDK = System.getProperty("test.jdk");
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+ private static final String OSNAME = System.getProperty("os.name");
+ private static final String ARCH;
+ private static final String LIBARCH;
+
+ static {
+ // magic with os.arch
+ String osarch = System.getProperty("os.arch");
+ switch (osarch) {
+ case "i386":
+ case "i486":
+ case "i586":
+ case "i686":
+ case "i786":
+ case "i886":
+ case "i986": {
+ ARCH = "i586";
+ break;
+ }
+ case "x86_64":
+ case "amd64": {
+ ARCH = "amd64";
+ break;
+ }
+ default: {
+ ARCH = osarch;
+ }
+ }
+ LIBARCH = ARCH.equals("i586") ? "i386" : ARCH;
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (TEST_CLASSES == null || TEST_CLASSES.isEmpty()) {
+ System.out.println("Test is designed to be run from jtreg only");
+ return;
+ }
+
+ String PLATFORM = "";
+ switch (OSNAME.toLowerCase()) {
+ case "linux": {
+ PLATFORM = "linux";
+ break;
+ }
+ case "sunos": {
+ PLATFORM = "solaris";
+ break;
+ }
+ default: {
+ System.out.println("Test not designed to run on this operating " +
+ "system (" + OSNAME + "), skipping...");
+ return;
+ }
+ }
+
+ String LAUNCHER = TEST_SRC + File.separator + PLATFORM + "-" + ARCH +
+ File.separator + "launcher";
+
+ final FileSystem FS = FileSystems.getDefault();
+ final boolean hasLauncher = Files.isExecutable(FS.getPath(LAUNCHER));
+ if (!hasLauncher) {
+ System.out.println("Launcher [" + LAUNCHER + "] does not exist. Skipping the test.");
+ return;
+ }
+
+ Path libjvmPath = findLibjvm(FS);
+ if (libjvmPath == null) {
+ throw new Error("Unable to locate 'libjvm.so' in " + TEST_JDK);
+ }
+
+ Process serverPrc = null, clientPrc = null;
+
+ try {
+ System.out.println("Starting custom launcher:");
+ System.out.println("=========================");
+ System.out.println(" launcher : " + LAUNCHER);
+ System.out.println(" libjvm : " + libjvmPath.toString());
+ System.out.println(" classpath : " + TEST_CLASSES);
+ ProcessBuilder server = new ProcessBuilder(LAUNCHER, libjvmPath.toString(), TEST_CLASSES, "TestApplication");
+
+ final AtomicReference<String> port = new AtomicReference<>();
+ final AtomicReference<String> pid = new AtomicReference<>();
+
+ serverPrc = ProcessTools.startProcess(
+ "Launcher",
+ server,
+ (String line) -> {
+ if (line.startsWith("port:")) {
+ port.set(line.split("\\:")[1]);
+ } else if (line.startsWith("pid:")) {
+ pid.set(line.split("\\:")[1]);
+ } else if (line.startsWith("waiting")) {
+ return true;
+ }
+ return false;
+ },
+ 5,
+ TimeUnit.SECONDS
+ );
+
+ System.out.println("Attaching test manager:");
+ System.out.println("=========================");
+ System.out.println(" PID : " + pid.get());
+ System.out.println(" shutdown port : " + port.get());
+
+ ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
+ "-cp",
+ TEST_CLASSES +
+ File.pathSeparator +
+ TEST_JDK +
+ File.separator +
+ "lib" +
+ File.separator +
+ "tools.jar",
+ "TestManager",
+ pid.get(),
+ port.get(),
+ "true"
+ );
+
+ clientPrc = ProcessTools.startProcess(
+ "TestManager",
+ client,
+ (String line) -> line.startsWith("Starting TestManager for PID"),
+ 10,
+ TimeUnit.SECONDS
+ );
+
+ int clientExitCode = clientPrc.waitFor();
+ int serverExitCode = serverPrc.waitFor();
+
+ if (clientExitCode != 0 || serverExitCode != 0) {
+ throw new Error("Test failed");
+ }
+ } finally {
+ if (clientPrc != null) {
+ clientPrc.destroy();
+ clientPrc.waitFor();
+ }
+ if (serverPrc != null) {
+ serverPrc.destroy();
+ serverPrc.waitFor();
+ }
+ }
+ }
+
+ private static Path findLibjvm(FileSystem FS) {
+ Path libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "jre", "lib", LIBARCH));
+ if (libjvmPath == null) {
+ libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "lib", LIBARCH));
+ }
+ return libjvmPath;
+ }
+
+ private static Path findLibjvm(Path libPath) {
+ // ARCH/libjvm.so -> ARCH/server/libjvm.so -> ARCH/client/libjvm.so
+ Path libjvmPath = libPath.resolve("libjvm.so");
+ if (isFileOk(libjvmPath)) {
+ return libjvmPath;
+ }
+ libjvmPath = libPath.resolve("server/libjvm.so");
+ if (isFileOk(libjvmPath)) {
+ return libjvmPath;
+ }
+ libjvmPath = libPath.resolve("client/libjvm.so");
+ if (isFileOk(libPath)) {
+ return libjvmPath;
+ }
+
+ return null;
+ }
+
+ private static boolean isFileOk(Path path) {
+ return Files.isRegularFile(path) && Files.isReadable(path);
+ }
+}
diff --git a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh
deleted file mode 100644
index 8622fba..0000000
--- a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2006, 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 6434402
-# @summary Start an application using a custom launcher and check that
-# a management tool can connect.
-#
-# @build TestManager TestApplication
-# @run shell CustomLauncherTest.sh
-
-#
-# Check we are run from jtreg
-#
-if [ -z "${TESTCLASSES}" ]; then
- echo "Test is designed to be run from jtreg only"
- exit 0
-fi
-
-#
-# For now this test passes silently on Windows - this means the test only
-# has to locate libjvm.so. Also $! is not reliable on some releases of MKS.
-#{
-OS=`uname -s`
-if [ "$OS" != "Linux" -a "$OS" != "SunOS" ]; then
- echo "Test not designed to run on this operating system, skipping..."
- exit 0
-fi
-
-#
-# Locate the custom launcher for this platform
-#
-PLATFORM=unknown
-ARCH=unknown
-if [ "$OS" = "SunOS" ]; then
- PLATFORM=solaris
- case "`uname -p`" in
- i[3-9]86)
- ARCH=i586
- ;;
- sparc)
- ARCH=sparc
- ;;
- esac
-else
- PLATFORM=linux
- case "`uname -m`" in
- i[3-6]86)
- ARCH=i586
- ;;
- x86_64)
- ARCH=amd64
- ;;
- esac
-fi
-
-
-#
-# On x86 the native libraries are in lib/i386 for
-# compatability reasons
-#
-if [ "$ARCH" = "i586" ]; then
- LIBARCH="i386"
-else
- LIBARCH=$ARCH
-fi
-
-
-#
-# Check that a custom launcher exists for this platform
-#
-LAUNCHER="${TESTSRC}/${PLATFORM}-${ARCH}/launcher"
-if [ ! -x "${LAUNCHER}" ]; then
- echo "${LAUNCHER} not found"
- exit 0
-fi
-
-#
-# Locate the libjvm.so library
-#
-JVMLIB="${TESTJAVA}/jre/lib/${LIBARCH}/client/libjvm.so"
-if [ ! -f "${JVMLIB}" ]; then
- JVMLIB="${TESTJAVA}/jre/lib/${LIBARCH}/server/libjvm.so"
- if [ ! -f "${JVMLIB}" ]; then
- JVMLIB="${TESTJAVA}/lib/${LIBARCH}/client/libjvm.so"
- if [ ! -f "${JVMLIB}" ]; then
- JVMLIB="${TESTJAVA}/lib/${LIBARCH}/serevr/libjvm.so"
- if [ ! -f "${JVMLIB}" ]; then
- echo "Unable to locate libjvm.so in ${TESTJAVA}"
- exit 1
- fi
- fi
- fi
-fi
-
-#
-# Start the VM
-#
-outputfile=${TESTCLASSES}/Test.out
-rm -f ${outputfile}
-
-echo ''
-echo "Starting custom launcher..."
-echo " launcher: ${LAUNCHER}"
-echo " libjvm: ${JVMLIB}"
-echo "classpath: ${TESTCLASSES}"
-
-
-${LAUNCHER} ${JVMLIB} ${TESTCLASSES} TestApplication > ${outputfile} &
-pid=$!
-
-# Wait for managed VM to startup (although this looks like a potentially
-# infinate loop, the framework will eventually kill it)
-echo "Waiting for TestAppication to test..."
-attempts=0
-while true; do
- sleep 1
- port=`tail -1 ${outputfile}`
- if [ ! -z "$port" ]; then
- # In case of errors wait time for output to be flushed
- sleep 1
- cat ${outputfile}
- break
- fi
- attempts=`expr $attempts + 1`
- echo "Waiting $attempts second(s) ..."
-done
-
-# Start the manager - this should connect to VM
-${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \
- TestManager $pid $port true
-if [ $? != 0 ]; then
- echo "Test failed"
- exit 1
-fi
-exit 0
diff --git a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
new file mode 100644
index 0000000..dc3b5de
--- /dev/null
+++ b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @test
+ * @library /lib/testlibrary
+ * @bug 5016507 6173612 6319776 6342019 6484550 8004926
+ * @summary Start a managed VM and test that a management tool can connect
+ * without connection or username/password details.
+ * TestManager will attempt a connection to the address obtained from
+ * both agent properties and jvmstat buffer.
+ * @build TestManager TestApplication
+ * @run main/timeout=300 LocalManagementTest
+ */
+
+import jdk.testlibrary.ProcessTools;
+
+public class LocalManagementTest {
+ private static final String TEST_CLASSES = System.getProperty("test.classes");
+ private static final String TEST_JDK = System.getProperty("test.jdk");
+
+ public static void main(String[] args) throws Exception {
+ int failures = 0;
+ for(Method m : LocalManagementTest.class.getDeclaredMethods()) {
+ if (Modifier.isStatic(m.getModifiers()) &&
+ m.getName().startsWith("test")) {
+ m.setAccessible(true);
+ try {
+ System.out.println(m.getName());
+ System.out.println("==========");
+ Boolean rslt = (Boolean)m.invoke(null);
+ if (!rslt) {
+ System.err.println(m.getName() + " failed");
+ failures++;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ failures++;
+ }
+ }
+ }
+ if (failures > 0) {
+ throw new Error("Test failed");
+ }
+ }
+
+ private static boolean test1() throws Exception {
+ return doTest("-Dcom.sun.management.jmxremote");
+ }
+
+ private static boolean test2() throws Exception {
+ Path agentPath = findAgent();
+ if (agentPath != null) {
+ String agent = agentPath.toString();
+ return doTest("-javaagent:" + agent);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * no args (blank) - manager should attach and start agent
+ */
+ private static boolean test3() throws Exception {
+ return doTest(null);
+ }
+
+ /**
+ * sanity check arguments to management-agent.jar
+ */
+ private static boolean test4() throws Exception {
+ Path agentPath = findAgent();
+ if (agentPath != null) {
+ ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(
+ "-javaagent:" + agentPath.toString() +
+ "=com.sun.management.jmxremote.port=7775," +
+ "com.sun.management.jmxremote.authenticate=false," +
+ "com.sun.management.jmxremote.ssl=false",
+ "-cp",
+ TEST_CLASSES,
+ "TestApplication",
+ "-exit"
+ );
+
+ Process prc = null;
+ try {
+ prc = ProcessTools.startProcess(
+ "TestApplication",
+ builder
+ );
+ int exitCode = prc.waitFor();
+ return exitCode == 0;
+ } finally {
+ if (prc != null) {
+ prc.destroy();
+ prc.waitFor();
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * use DNS-only name service
+ */
+ private static boolean test5() throws Exception {
+ return doTest("-Dsun.net.spi.namservice.provider.1=\"dns,sun\"");
+ }
+
+ private static Path findAgent() {
+ FileSystem FS = FileSystems.getDefault();
+ Path agentPath = FS.getPath(
+ TEST_JDK, "jre", "lib", "management-agent.jar"
+ );
+ if (!isFileOk(agentPath)) {
+ agentPath = FS.getPath(
+ TEST_JDK, "lib", "management-agent.jar"
+ );
+ }
+ if (!isFileOk(agentPath)) {
+ System.err.println("Can not locate management-agent.jar");
+ return null;
+ }
+ return agentPath;
+ }
+
+ private static boolean isFileOk(Path path) {
+ return Files.isRegularFile(path) && Files.isReadable(path);
+ }
+
+ private static boolean doTest(String arg) throws Exception {
+ List<String> args = new ArrayList<>();
+ args.add("-cp");
+ args.add(TEST_CLASSES);
+
+ if (arg != null) {
+ args.add(arg);
+ }
+ args.add("TestApplication");
+ ProcessBuilder server = ProcessTools.createJavaProcessBuilder(
+ args.toArray(new String[args.size()])
+ );
+
+ Process serverPrc = null, clientPrc = null;
+ try {
+ final AtomicReference<String> port = new AtomicReference<>();
+ final AtomicReference<String> pid = new AtomicReference<>();
+
+ serverPrc = ProcessTools.startProcess(
+ "TestApplication",
+ server,
+ (String line) -> {
+ if (line.startsWith("port:")) {
+ port.set(line.split("\\:")[1]);
+ } else if (line.startsWith("pid:")) {
+ pid.set(line.split("\\:")[1]);
+ } else if (line.startsWith("waiting")) {
+ return true;
+ }
+ return false;
+ },
+ 5,
+ TimeUnit.SECONDS
+ );
+
+ System.out.println("Attaching test manager:");
+ System.out.println("=========================");
+ System.out.println(" PID : " + pid.get());
+ System.out.println(" shutdown port : " + port.get());
+
+ ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
+ "-cp",
+ TEST_CLASSES +
+ File.pathSeparator +
+ TEST_JDK +
+ File.separator +
+ "lib" +
+ File.separator +
+ "tools.jar",
+ "TestManager",
+ pid.get(),
+ port.get(),
+ "true"
+ );
+
+ clientPrc = ProcessTools.startProcess(
+ "TestManager",
+ client,
+ (String line) -> line.startsWith("Starting TestManager for PID"),
+ 10,
+ TimeUnit.SECONDS
+ );
+
+ int clientExitCode = clientPrc.waitFor();
+ int serverExitCode = serverPrc.waitFor();
+ return clientExitCode == 0 && serverExitCode == 0;
+ } finally {
+ if (clientPrc != null) {
+ System.out.println("Stopping process " + clientPrc);
+ clientPrc.destroy();
+ clientPrc.waitFor();
+ }
+ if (serverPrc != null) {
+ System.out.println("Stopping process " + serverPrc);
+ serverPrc.destroy();
+ serverPrc.waitFor();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh
deleted file mode 100644
index 7338cbe..0000000
--- a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2004, 2006, 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 5016507 6173612 6319776 6342019 6484550
-# @summary Start a managed VM and test that a management tool can connect
-# without connection or username/password details.
-# TestManager will attempt a connection to the address obtained from
-# both agent properties and jvmstat buffer.
-#
-# @build TestManager TestApplication
-# @run shell/timeout=300 LocalManagementTest.sh
-
-
-doTest()
-{
- echo ''
-
- outputfile=${TESTCLASSES}/Test.out
- rm -f ${outputfile}
-
- # Start VM with given options
- echo "+ $JAVA ${TESTVMOPTS} $1 Test"
- $JAVA ${TESTVMOPTS} $1 TestApplication > ${outputfile}&
- pid=$!
-
- # Wait for managed VM to startup
- echo "Waiting for VM to startup..."
- attempts=0
- while true; do
- sleep 1
- port=`tail -1 ${outputfile}`
- if [ ! -z "$port" ]; then
- # In case of errors wait time for output to be flushed
- sleep 1
- cat ${outputfile}
- break
- fi
- attempts=`expr $attempts + 1`
- echo "Waiting $attempts second(s) ..."
- done
-
- # Start the manager - this should connect to VM
- sh -xc "$JAVA ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \
- TestManager $pid $port" 2>&1
- if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-}
-
-
-# Check we are run from jtreg
-if [ -z "${TESTCLASSES}" ]; then
- echo "Test is designed to be run from jtreg only"
- exit 0
-fi
-
-# For now this test passes silently on Windows - there are 2 reasons
-# to skip it :-
-#
-# 1. No jstat instrumentation buffers if FAT32 so need
-# -XX:+PerfBypassFileSystemCheck
-# 2. $! is used to get the pid of the created process but it's not
-# reliable on older versions of MKS. Also negative pids are returned
-# on Windows 98.
-
-os=`uname -s`
-if [ "$os" != "Linux" -a "$os" != "SunOS" ]; then
- echo "Test not designed to run on this operating system, skipping..."
- exit 0
-fi
-
-JAVA=${TESTJAVA}/bin/java
-CLASSPATH=${TESTCLASSES}
-export CLASSPATH
-
-failures=0
-
-# Test 1
-doTest "-Dcom.sun.management.jmxremote"
-
-# Test 2
-AGENT="${TESTJAVA}/jre/lib/management-agent.jar"
-if [ ! -f ${AGENT} ]; then
- AGENT="${TESTJAVA}/lib/management-agent.jar"
-fi
-doTest "-javaagent:${AGENT}"
-
-# Test 3 - no args (blank) - manager should attach and start agent
-doTest " "
-
-# Test 4 - sanity check arguments to management-agent.jar
-echo ' '
-sh -xc "${JAVA} ${TESTVMOPTS} -javaagent:${AGENT}=com.sun.management.jmxremote.port=7775,\
-com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false \
- TestApplication -exit" 2>&1
-if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-
-# Test 5 - use DNS-only name service
-doTest "-Dsun.net.spi.namservice.provider.1=\"dns,sun\""
-
-#
-# Results
-#
-echo ''
-if [ $failures -gt 0 ];
- then echo "$failures test(s) failed";
- else echo "All test(s) passed"; fi
-exit $failures
-
diff --git a/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java b/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java
index cb96e66..adda49b 100644
--- a/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java
+++ b/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -24,14 +24,15 @@
import java.io.File;
import java.io.FileInputStream;
-import java.io.InputStream;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.rmi.server.ExportException;
import java.util.Properties;
import java.util.Iterator;
import java.util.Set;
-import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -54,7 +55,7 @@
* bootstrap & connection test will fail.</p>
*
* <p>The rmi port number can be specified with the "rmi.port" system property.
- * If not, this test will use 12424</p>
+ * If not, this test will use the first available port</p>
*
* <p>When called with some argument, the main() will interprete its args to
* be Java M&M configuration file names. The filenames are expected to end
@@ -69,7 +70,8 @@
* <p>Debug traces are logged in "sun.management.test"</p>
**/
public class RmiBootstrapTest {
-
+ // the number of consecutive ports to test for availability
+ private static final int PORT_TEST_LEN = 800;
static TestLogger log =
new TestLogger("RmiBootstrapTest");
@@ -78,6 +80,7 @@
* to avoid falling into "port number already in use" problems.
**/
static int testPort = 0;
+ static int basePort = 0;
/**
* Default values for RMI configuration properties.
@@ -624,7 +627,7 @@
* eventually cleans up by calling ConnectorBootstrap.terminate().
* @return null if the test succeeds, an error message otherwise.
**/
- private String testConfiguration(File file,int port) {
+ private String testConfiguration(File file,int port) throws BindException {
final String path;
try {
@@ -644,7 +647,7 @@
System.out.println("***");
System.setProperty("com.sun.management.jmxremote.port",
- Integer.toString(port));
+ Integer.toString(port));
if (path != null)
System.setProperty("com.sun.management.config.file", path);
else
@@ -661,6 +664,11 @@
try {
cs = ConnectorBootstrap.initialize();
} catch (AgentConfigurationError x) {
+ if (x.getCause() instanceof ExportException) {
+ if (x.getCause().getCause() instanceof BindException) {
+ throw (BindException)x.getCause().getCause();
+ }
+ }
final String err = "Failed to initialize connector:" +
"\n\tcom.sun.management.jmxremote.port=" + port +
((path!=null)?"\n\tcom.sun.management.config.file="+path:
@@ -713,7 +721,15 @@
* @return null if the test succeeds, an error message otherwise.
**/
private String testConfigurationKo(File conf,int port) {
- final String errStr = testConfiguration(conf,port+testPort++);
+ String errStr = null;
+ for (int i = 0; i < PORT_TEST_LEN; i++) {
+ try {
+ errStr = testConfiguration(conf,port+testPort++);
+ break;
+ } catch (BindException e) {
+ // port conflict; try another port
+ }
+ }
if (errStr == null) {
return "Configuration " +
conf + " should have failed!";
@@ -733,11 +749,21 @@
**/
private String testConfigurationFile(String fileName) {
File file = new File(fileName);
- final String portStr = System.getProperty("rmi.port","12424");
- final int port = Integer.parseInt(portStr);
+ final String portStr = System.getProperty("rmi.port",null);
+ final int port = portStr != null ?
+ Integer.parseInt(portStr) : basePort;
if (fileName.endsWith("ok.properties")) {
- return testConfiguration(file,port+testPort++);
+ String errStr = null;
+ for (int i = 0; i < PORT_TEST_LEN; i++) {
+ try {
+ errStr = testConfiguration(file,port+testPort++);
+ return errStr;
+ } catch (BindException e) {
+ // port conflict; try another port
+ }
+ }
+ return "Can not locate available port";
}
if (fileName.endsWith("ko.properties")) {
return testConfigurationKo(file,port+testPort++);
@@ -752,8 +778,9 @@
* @throws RuntimeException if the test fails.
**/
public void runko() {
- final String portStr = System.getProperty("rmi.port","12424");
- final int port = Integer.parseInt(portStr);
+ final String portStr = System.getProperty("rmi.port",null);
+ final int port = portStr != null ?
+ Integer.parseInt(portStr) : basePort;
final File[] conf = findConfigurationFilesKo();
if ((conf == null)||(conf.length == 0))
throw new RuntimeException("No configuration found");
@@ -774,15 +801,23 @@
* @throws RuntimeException if the test fails.
**/
public void runok() {
- final String portStr = System.getProperty("rmi.port","12424");
- final int port = Integer.parseInt(portStr);
+ final String portStr = System.getProperty("rmi.port",null);
+ final int port = portStr != null ?
+ Integer.parseInt(portStr) : basePort;
final File[] conf = findConfigurationFilesOk();
if ((conf == null)||(conf.length == 0))
throw new RuntimeException("No configuration found");
- String errStr;
+ String errStr = null;
for (int i=0;i<conf.length;i++) {
- errStr = testConfiguration(conf[i],port+testPort++);
+ for (int j = 0; j < PORT_TEST_LEN; i++) {
+ try {
+ errStr = testConfiguration(conf[i],port+testPort++);
+ break;
+ } catch (BindException e) {
+ // port conflict; try another port
+ }
+ }
if (errStr != null) {
throw new RuntimeException(errStr);
}
@@ -835,7 +870,8 @@
* Calls run(args[]).
* exit(1) if the test fails.
**/
- public static void main(String args[]) {
+ public static void main(String args[]) throws Exception {
+ setupBasePort();
RmiBootstrapTest manager = new RmiBootstrapTest();
try {
manager.run(args);
@@ -850,4 +886,9 @@
System.out.println("**** Test RmiBootstrap Passed ****");
}
+ private static void setupBasePort() throws IOException {
+ try (ServerSocket s = new ServerSocket(0)) {
+ basePort = s.getLocalPort() + 1;
+ }
+ }
}
diff --git a/test/sun/management/jmxremote/bootstrap/TestApplication.java b/test/sun/management/jmxremote/bootstrap/TestApplication.java
index 17816b9..5d6ca2b 100644
--- a/test/sun/management/jmxremote/bootstrap/TestApplication.java
+++ b/test/sun/management/jmxremote/bootstrap/TestApplication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -24,14 +24,18 @@
/*
*
*
- * A test "application" used by unit test LocalManagementTest.sh. This
- * application binds to some random port, prints the port number to
- * standard output, waits for somebody to connect, and then shuts down.
+ * A test "application" used by unit tests -
+ * LocalManagementTest.java, CustomLauncherTest.java.
+ * This application binds to some random port, prints its pid and
+ * the port number to standard output, waits for somebody to connect,
+ * and then shuts down.
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
+import jdk.testlibrary.ProcessTools;
+
public class TestApplication {
public static void main(String[] args) throws IOException {
// Some tests require the application to exit immediately
@@ -43,8 +47,17 @@
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
- // signal test that we are started - do not remove this line!!
- System.out.println(port);
+ int pid = -1;
+ try {
+ pid = ProcessTools.getProcessId();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ // signal test that we are started - do not remove these lines!!
+ System.out.println("port:" + port);
+ System.out.println("pid:" + pid);
+ System.out.println("waiting for the manager ...");
System.out.flush();
// wait for manager to connect
diff --git a/test/sun/management/jmxremote/bootstrap/TestManager.java b/test/sun/management/jmxremote/bootstrap/TestManager.java
index 379739a..4495c2d 100644
--- a/test/sun/management/jmxremote/bootstrap/TestManager.java
+++ b/test/sun/management/jmxremote/bootstrap/TestManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -24,7 +24,8 @@
/*
*
*
- * A test "management tool" used by unit test LocalManagementTest.sh.
+ * A test "management tool" used by unit tests -
+ * LocalManagementTest.java, CustomLauncherTest.java
*
* Usage: java TestManager <pid> <port>
*
@@ -32,8 +33,6 @@
* TCP port is used to shutdown the application.
*/
import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnector;
@@ -43,7 +42,6 @@
import java.net.InetSocketAddress;
import java.io.File;
import java.io.IOException;
-import java.util.Properties;
// Sun specific
import com.sun.tools.attach.VirtualMachine;
@@ -111,6 +109,8 @@
"com.sun.management.jmxremote.localConnectorAddress";
public static void main(String[] args) throws Exception {
String pid = args[0]; // pid as a string
+ System.out.println("Starting TestManager for PID = " + pid);
+ System.out.flush();
VirtualMachine vm = VirtualMachine.attach(pid);
String agentPropLocalConnectorAddress = (String)
@@ -140,7 +140,6 @@
System.out.println("Testing the connector address from jvmstat buffer");
connect(pid, jvmstatLocalConnectorAddress);
-
// Shutdown application
int port = Integer.parseInt(args[1]);
System.out.println("Shutdown process via TCP port: " + port);
diff --git a/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher b/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher
new file mode 100644
index 0000000..6df223c
--- /dev/null
+++ b/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher
Binary files differ
diff --git a/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh b/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh
index e2e7598..4d67216 100644
--- a/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh
+++ b/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh
@@ -551,6 +551,11 @@
esac
done
+if [ "${COMPILEJAVA}" = "" ]
+then
+ COMPILEJAVA=${TESTJAVA}
+fi
+
if [ ${_compile} = "yes" ]
then
_compile
diff --git a/test/sun/nio/cs/TestIBMBugs.java b/test/sun/nio/cs/TestIBMBugs.java
index 9bf732c..96404a4 100644
--- a/test/sun/nio/cs/TestIBMBugs.java
+++ b/test/sun/nio/cs/TestIBMBugs.java
@@ -147,16 +147,17 @@
}
private static void bug6569191 () throws Exception {
- byte[] bs = new byte[] { (byte)0x81, (byte)0xad,
- (byte)0x81, (byte)0xae,
- (byte)0x81, (byte)0xaf,
- (byte)0x81, (byte)0xb0,
- (byte)0x85, (byte)0x81,
- (byte)0x85, (byte)0x87,
- (byte)0x85, (byte)0xe0,
- (byte)0x85, (byte)0xf0 };
+ byte[] bs = new byte[] { (byte)0x81, (byte)0xad, // fffd ff6d
+ (byte)0x81, (byte)0xae, // fffd ff6e
+ (byte)0x81, (byte)0xaf, // fffd ff6f
+ (byte)0x81, (byte)0xb0, // fffd ff70
+ (byte)0x85, (byte)0x81, // fffd ->
+ (byte)0x85, (byte)0x87, // 2266 ->
+ (byte)0x85, (byte)0xe0, // 32a4 ->
+ (byte)0x85, (byte)0xf0 };// 7165 fffd
String s = new String(bs, "Cp943");
- if (!"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd"
+ // see DoubleByte for how the unmappables are handled
+ if (!"\ufffd\uff6d\ufffd\uff6e\ufffd\uff6f\ufffd\uff70\ufffd\u2266\u32a4\u7165\ufffd"
.equals(s))
throw new Exception("Cp943 failed");
}
diff --git a/test/sun/nio/cs/TestUnmappable.java b/test/sun/nio/cs/TestUnmappable.java
new file mode 100644
index 0000000..6273807
--- /dev/null
+++ b/test/sun/nio/cs/TestUnmappable.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8008386
+ * @summary (cs) Unmappable leading should be decoded to replacement.
+ * Tests for Shift_JIS and MS932 decoding
+ * @run main TestUnmappable
+ */
+
+import java.nio.*;
+import java.nio.charset.*;
+
+public class TestUnmappable {
+ public static void main(String args[]) throws Exception {
+
+ // illegal leading character test
+ byte[][] inputBytes = {
+ // Shift_JIS
+ {(byte)0xce, (byte)0xa0, (byte)0xce, (byte)0x7a},
+ // MS932
+ {(byte)0x3c, (byte)0x21, (byte)0x2d, (byte)0x2d,
+ (byte)0xe5, (byte)0xaf, (byte)0xbe, (byte)0xe5,
+ (byte)0xbf, (byte)0x9c, (byte)0x2d, (byte)0x2d,
+ (byte)0x3e, (byte)0xd, (byte)0xa },
+ {(byte)0x81, (byte)0xad},
+ // PCK
+ {(byte)0xef, (byte)0x90},
+ {(byte)0x91, (byte)0xfd}
+ };
+
+ String[] charsets = { "Shift_JIS", "MS932", "PCK" };
+ String[] expectedStrings = {
+ // Shift_JIS
+ "0xce 0x3f 0xce 0x7a ",
+ // MS932
+ "0x3c 0x21 0x2d 0x2d 0xe5 0xaf 0xbe 0xe5 0xbf " +
+ "0x3f 0x2d 0x2d 0x3e 0xd 0xa ",
+ "0x3f 0xad ",
+ // PCK
+ "0x3f 0x3f ",
+ "0x3f "};
+
+ for (int i = 0; i < charsets.length; i++) {
+ String ret = new String(inputBytes[i], charsets[i]);
+ String bString = getByteString(ret.getBytes(Charset.forName(charsets[i])));
+ if (expectedStrings[i].length() != bString.length()
+ || ! expectedStrings[i].equals(bString)){
+ throw new Exception("ByteToChar for " + charsets[i]
+ + " does not work correctly.\n" +
+ "Expected: " + expectedStrings[i] + "\n" +
+ "Received: " + bString);
+ }
+ }
+ }
+
+ private static String getByteString(byte[] bytes) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < bytes.length; i++) {
+ sb.append("0x" + Integer.toHexString((int)(bytes[i] & 0xFF)) + " ");
+ }
+ return sb.toString();
+ }
+}
diff --git a/test/sun/reflect/Reflection/GetCallerClassWithDepth.java b/test/sun/reflect/Reflection/GetCallerClassWithDepth.java
new file mode 100644
index 0000000..33eefd5
--- /dev/null
+++ b/test/sun/reflect/Reflection/GetCallerClassWithDepth.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8025799
+ * @summary sun.reflect.Reflection.getCallerClass(int)
+ * @run main GetCallerClassWithDepth
+ */
+
+public class GetCallerClassWithDepth {
+ public static void main(String[] args) throws Exception {
+ Class<?> c = Test.test();
+ assertEquals(c, GetCallerClassWithDepth.class);
+ Class<?> caller = Test.caller();
+ assertEquals(caller, GetCallerClassWithDepth.class);
+ Test.selfTest();
+
+ try {
+ sun.reflect.Reflection.getCallerClass(-1);
+ throw new RuntimeException("getCallerClass(-1) should fail");
+ } catch (Error e) {
+ System.out.println("Expected: " + e.getMessage());
+ }
+ }
+
+ public Class<?> getCallerClass() {
+ // 0: Reflection 1: getCallerClass 2: Test.test 3: main
+ return sun.reflect.Reflection.getCallerClass(3);
+ }
+
+ static void assertEquals(Class<?> c, Class<?> expected) {
+ if (c != expected) {
+ throw new RuntimeException("Incorrect caller: " + c);
+ }
+ }
+
+ static class Test {
+ // Returns the caller of this method
+ public static Class<?> test() {
+ return new GetCallerClassWithDepth().getCallerClass();
+ }
+
+ // Returns the caller of this method
+ public static Class<?> caller() {
+ // 0: Reflection 1: Test.caller 2: main
+ return sun.reflect.Reflection.getCallerClass(2);
+ }
+ public static void selfTest() {
+ // 0: Reflection 1: Test.selfTest
+ Class<?> c = sun.reflect.Reflection.getCallerClass(1);
+ assertEquals(c, Test.class);
+ Inner1.deep();
+ }
+
+ static class Inner1 {
+ static void deep() {
+ deeper();
+ }
+ static void deeper() {
+ Inner2.deepest();
+ }
+ static class Inner2 {
+ static void deepest() {
+ // 0: Reflection 1: deepest 2: deeper 3: deep 4: Test.selfTest
+ Class<?> c = sun.reflect.Reflection.getCallerClass(4);
+ assertEquals(c, Test.class);
+ }
+ }
+ }
+ }
+}
diff --git a/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java b/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java
new file mode 100644
index 0000000..59c39fc
--- /dev/null
+++ b/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8023862
+ * @summary Verify that the default value of the java.rmi.server.disableHttp
+ * has been changed from false to true.
+ * @compile -XDignore.symbol.file DisableHttpDefaultValue.java
+ *
+ * @run main/othervm DisableHttpDefaultValue true
+ * @run main/othervm -Djava.rmi.server.disableHttp DisableHttpDefaultValue false
+ * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false
+ * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false
+ * @run main/othervm -Djava.rmi.server.disableHttp=true DisableHttpDefaultValue true
+ */
+
+import sun.rmi.transport.proxy.RMIMasterSocketFactory;
+
+public class DisableHttpDefaultValue {
+ /**
+ * Subclass RMIMasterSocketFactory to get access to
+ * protected field altFactoryList. This list has a
+ * zero size if proxying is disabled.
+ */
+ static class SocketFactory extends RMIMasterSocketFactory {
+ boolean proxyDisabled() {
+ return altFactoryList.size() == 0;
+ }
+ }
+
+ /**
+ * Takes a single arg, which is the expected boolean value of
+ * java.rmi.server.disableHttp.
+ */
+ public static void main(String[] args) throws Exception {
+ // Force there to be a proxy host, so that we are able to
+ // tell whether proxying is enabled or disabled.
+ System.setProperty("http.proxyHost", "proxy.example.com");
+
+ String propval = System.getProperty("java.rmi.server.disableHttp");
+ String propdisp = (propval == null) ? "null" : ("\"" + propval + "\"");
+ boolean expected = Boolean.parseBoolean(args[0]);
+ boolean actual = new SocketFactory().proxyDisabled();
+ System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual);
+ if (expected != actual)
+ throw new AssertionError();
+ }
+}
diff --git a/test/sun/security/pkcs12/PKCS12SameKeyId.java b/test/sun/security/pkcs12/PKCS12SameKeyId.java
index f65292a..400ba0e 100644
--- a/test/sun/security/pkcs12/PKCS12SameKeyId.java
+++ b/test/sun/security/pkcs12/PKCS12SameKeyId.java
@@ -60,7 +60,7 @@
for (int i=0; i<SIZE; i++) {
System.err.print(".");
String cmd = "-keystore " + JKSFILE
- + " -storepass changeit -keypass changeit "
+ + " -storepass changeit -keypass changeit -keyalg rsa "
+ "-genkeypair -alias p" + i + " -dname CN=" + i;
sun.security.tools.keytool.Main.main(cmd.split(" "));
}
diff --git a/test/sun/security/tools/jarsigner/TimestampCheck.java b/test/sun/security/tools/jarsigner/TimestampCheck.java
index 237d61f..ab7d5c7 100644
--- a/test/sun/security/tools/jarsigner/TimestampCheck.java
+++ b/test/sun/security/tools/jarsigner/TimestampCheck.java
@@ -185,7 +185,7 @@
DerOutputStream tstInfo2 = new DerOutputStream();
tstInfo2.putOctetString(tstInfo.toByteArray());
- Signature sig = Signature.getInstance("SHA1withDSA");
+ Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign((PrivateKey)(ks.getKey(
alias, "changeit".toCharArray())));
sig.update(tstInfo.toByteArray());
diff --git a/test/sun/security/tools/jarsigner/checkusage.sh b/test/sun/security/tools/jarsigner/checkusage.sh
index 957df16..e1f42a5 100644
--- a/test/sun/security/tools/jarsigner/checkusage.sh
+++ b/test/sun/security/tools/jarsigner/checkusage.sh
@@ -45,7 +45,7 @@
;;
esac
-KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit"
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keyalg rsa"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner"
diff --git a/test/sun/security/tools/jarsigner/collator.sh b/test/sun/security/tools/jarsigner/collator.sh
index 06e21aa..a78d4b9 100644
--- a/test/sun/security/tools/jarsigner/collator.sh
+++ b/test/sun/security/tools/jarsigner/collator.sh
@@ -47,7 +47,7 @@
JFILE=collator.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
- -keystore $KS"
+ -keyalg rsa -keystore $KS"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
diff --git a/test/sun/security/tools/jarsigner/crl.sh b/test/sun/security/tools/jarsigner/crl.sh
index 2d7f523..c18817c 100644
--- a/test/sun/security/tools/jarsigner/crl.sh
+++ b/test/sun/security/tools/jarsigner/crl.sh
@@ -45,7 +45,7 @@
KS=crl.jks
-KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa"
rm $KS 2> /dev/null
diff --git a/test/sun/security/tools/jarsigner/jvindex.sh b/test/sun/security/tools/jarsigner/jvindex.sh
index c4435b6..7c8ebdd 100644
--- a/test/sun/security/tools/jarsigner/jvindex.sh
+++ b/test/sun/security/tools/jarsigner/jvindex.sh
@@ -47,7 +47,7 @@
JFILE=jvindex.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
- -keystore $KS"
+ -keystore $KS -keyalg rsa"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
diff --git a/test/sun/security/tools/jarsigner/newsize7.sh b/test/sun/security/tools/jarsigner/newsize7.sh
index cb887c2..27ac5b9 100644
--- a/test/sun/security/tools/jarsigner/newsize7.sh
+++ b/test/sun/security/tools/jarsigner/newsize7.sh
@@ -51,7 +51,7 @@
KSFILE=ns7.jks
-KT="${TESTJAVA}${FS}bin${FS}keytool -keystore ns7.jks -storepass changeit -keypass changeit"
+KT="${TESTJAVA}${FS}bin${FS}keytool -keystore ns7.jks -storepass changeit -keypass changeit -keyalg rsa"
JAR="${TESTJAVA}${FS}bin${FS}jar"
JS="${TESTJAVA}${FS}bin${FS}jarsigner -keystore ns7.jks -storepass changeit"
diff --git a/test/sun/security/tools/jarsigner/onlymanifest.sh b/test/sun/security/tools/jarsigner/onlymanifest.sh
index 5ea9578..16e7d77 100644
--- a/test/sun/security/tools/jarsigner/onlymanifest.sh
+++ b/test/sun/security/tools/jarsigner/onlymanifest.sh
@@ -46,7 +46,7 @@
JFILE=onlymanifest.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
- -keystore $KS"
+ -keystore $KS -keyalg rsa"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
diff --git a/test/sun/security/tools/jarsigner/passtype.sh b/test/sun/security/tools/jarsigner/passtype.sh
index b649668..c3ce7d5 100644
--- a/test/sun/security/tools/jarsigner/passtype.sh
+++ b/test/sun/security/tools/jarsigner/passtype.sh
@@ -45,7 +45,7 @@
KS=pt.jks
JFILE=pt.jar
-KT="$TESTJAVA${FS}bin${FS}keytool -keystore $KS -validity 300"
+KT="$TESTJAVA${FS}bin${FS}keytool -keystore $KS -validity 300 -keyalg rsa"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
diff --git a/test/sun/security/tools/jarsigner/samename.sh b/test/sun/security/tools/jarsigner/samename.sh
index 2b9203e..a89caa1 100644
--- a/test/sun/security/tools/jarsigner/samename.sh
+++ b/test/sun/security/tools/jarsigner/samename.sh
@@ -47,7 +47,7 @@
KS=samename.jks
JFILE=em.jar
-KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
diff --git a/test/sun/security/tools/jarsigner/ts.sh b/test/sun/security/tools/jarsigner/ts.sh
index e318ca6..b389226 100644
--- a/test/sun/security/tools/jarsigner/ts.sh
+++ b/test/sun/security/tools/jarsigner/ts.sh
@@ -53,7 +53,7 @@
JAR="${TESTJAVA}${FS}bin${FS}jar"
JAVA="${TESTJAVA}${FS}bin${FS}java"
JAVAC="${TESTJAVA}${FS}bin${FS}javac"
-KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit"
+KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa"
rm tsks
echo Nothing > A
diff --git a/test/sun/security/tools/keytool/CloseFile.java b/test/sun/security/tools/keytool/CloseFile.java
index 82c3e44..95fd4c2 100644
--- a/test/sun/security/tools/keytool/CloseFile.java
+++ b/test/sun/security/tools/keytool/CloseFile.java
@@ -59,7 +59,7 @@
}
static void run(String s) throws Exception {
- sun.security.tools.keytool.Main.main((s+" -debug").split(" "));
+ sun.security.tools.keytool.Main.main((s+" -debug -keyalg rsa").split(" "));
}
static void remove(String filename, boolean check) {
new File(filename).delete();
diff --git a/test/sun/security/tools/keytool/ListKeychainStore.sh b/test/sun/security/tools/keytool/ListKeychainStore.sh
index 63fb0f8..48b1a5e 100644
--- a/test/sun/security/tools/keytool/ListKeychainStore.sh
+++ b/test/sun/security/tools/keytool/ListKeychainStore.sh
@@ -71,6 +71,7 @@
-storetype PKCS12 \
-keystore $TEMPORARY_P12 \
-storepass $PWD \
+ -keyalg rsa \
-dname "CN=$i,OU=$i,O=$i,ST=$i,C=US" \
-alias 7133495-$i
diff --git a/test/sun/security/tools/keytool/StartDateTest.java b/test/sun/security/tools/keytool/StartDateTest.java
index 597c745..96282a0 100644
--- a/test/sun/security/tools/keytool/StartDateTest.java
+++ b/test/sun/security/tools/keytool/StartDateTest.java
@@ -49,7 +49,7 @@
new File("jks").delete();
run("-keystore jks -storetype jks -storepass changeit -keypass changeit -alias me " +
- "-genkeypair -dname CN=Haha -startdate +1y");
+ "-keyalg rsa -genkeypair -dname CN=Haha -startdate +1y");
cal.setTime(getIssueDate());
System.out.println(cal);
if (cal.get(Calendar.YEAR) != year + 1) {
diff --git a/test/sun/security/tools/keytool/UnknownAndUnparseable.java b/test/sun/security/tools/keytool/UnknownAndUnparseable.java
index cb8cbad..7c72a4d 100644
--- a/test/sun/security/tools/keytool/UnknownAndUnparseable.java
+++ b/test/sun/security/tools/keytool/UnknownAndUnparseable.java
@@ -43,7 +43,7 @@
// Create a cert with an unknown extension: 1.2.3.4, and an invalid
// KeyUsage extension
String genkey = s
- + "-genkeypair -alias a -dname CN=A -ext 1.2.3.4=1234 "
+ + "-genkeypair -alias a -dname CN=A -ext 1.2.3.4=1234 -keyalg rsa "
+ "-ext " + PKIXExtensions.KeyUsage_Id.toString() + "=5678";
sun.security.tools.keytool.Main.main(genkey.split(" "));
diff --git a/test/sun/security/tools/keytool/emptysubject.sh b/test/sun/security/tools/keytool/emptysubject.sh
index 3d9ca06..19b61f8 100644
--- a/test/sun/security/tools/keytool/emptysubject.sh
+++ b/test/sun/security/tools/keytool/emptysubject.sh
@@ -45,7 +45,7 @@
esac
KS=emptysubject.jks
-KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa"
rm $KS
diff --git a/test/sun/security/tools/keytool/importreadall.sh b/test/sun/security/tools/keytool/importreadall.sh
index cbf67c1..6a223de 100644
--- a/test/sun/security/tools/keytool/importreadall.sh
+++ b/test/sun/security/tools/keytool/importreadall.sh
@@ -49,7 +49,7 @@
;;
esac
-KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -keystore importreadall.jks -storepass changeit -keypass changeit"
+KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -keystore importreadall.jks -storepass changeit -keypass changeit -keyalg rsa"
# In case the test is run twice in the same directory
diff --git a/test/sun/security/tools/keytool/p12importks.sh b/test/sun/security/tools/keytool/p12importks.sh
index efdb56a..33462b2 100644
--- a/test/sun/security/tools/keytool/p12importks.sh
+++ b/test/sun/security/tools/keytool/p12importks.sh
@@ -50,7 +50,7 @@
rm jks 2> /dev/null
$KT -genkeypair -keystore jks -storetype jks -alias me -dname CN=Me \
- -storepass pass1111 -keypass pass1111 || exit 11
+ -keyalg rsa -storepass pass1111 -keypass pass1111 || exit 11
# Cannot only change storepass
rm p12 2> /dev/null
@@ -85,7 +85,7 @@
rm jks 2> /dev/null
$KT -genkeypair -keystore jks -storetype jks -alias me -dname CN=Me \
- -storepass pass1111 -keypass pass2222 || exit 21
+ -keyalg rsa -storepass pass1111 -keypass pass2222 || exit 21
# Can use old keypass as new storepass so new storepass and keypass are same
rm p12 2> /dev/null
diff --git a/test/sun/security/tools/keytool/readjar.sh b/test/sun/security/tools/keytool/readjar.sh
index 037a908..31324a6 100644
--- a/test/sun/security/tools/keytool/readjar.sh
+++ b/test/sun/security/tools/keytool/readjar.sh
@@ -46,7 +46,7 @@
KS=readjar.jks
rm $KS
$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS \
- -alias x -dname CN=X -genkeypair
+ -keyalg rsa -alias x -dname CN=X -genkeypair
$COMPILEJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS} cvf readjar.jar $KS
$COMPILEJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -storepass changeit -keystore $KS readjar.jar x
diff --git a/test/sun/security/tools/keytool/selfissued.sh b/test/sun/security/tools/keytool/selfissued.sh
index 4fa7cfc..c02c66a 100644
--- a/test/sun/security/tools/keytool/selfissued.sh
+++ b/test/sun/security/tools/keytool/selfissued.sh
@@ -45,7 +45,7 @@
esac
KS=selfsigned.jks
-KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS -keyalg rsa"
rm $KS
diff --git a/test/sun/security/tools/keytool/trystore.sh b/test/sun/security/tools/keytool/trystore.sh
index ffe4ebe..2dcf988 100644
--- a/test/sun/security/tools/keytool/trystore.sh
+++ b/test/sun/security/tools/keytool/trystore.sh
@@ -43,7 +43,7 @@
rm trystore.jks 2> /dev/null
-KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -storetype jks -keystore trystore.jks"
+KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -storetype jks -keystore trystore.jks -keyalg rsa"
$KEYTOOL -genkeypair -alias a -dname CN=A -storepass changeit -keypass changeit
$KEYTOOL -genkeypair -alias b -dname CN=B -storepass changeit -keypass changeit
diff --git a/test/sun/security/validator/certreplace.sh b/test/sun/security/validator/certreplace.sh
index 78f821b..5104833 100644
--- a/test/sun/security/validator/certreplace.sh
+++ b/test/sun/security/validator/certreplace.sh
@@ -48,7 +48,7 @@
esac
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit \
- -keypass changeit -keystore certreplace.jks"
+ -keypass changeit -keystore certreplace.jks -keyalg rsa"
JAVAC=$COMPILEJAVA${FS}bin${FS}javac
JAVA=$TESTJAVA${FS}bin${FS}java
diff --git a/test/sun/security/validator/samedn.sh b/test/sun/security/validator/samedn.sh
index 0e3e837..17d5af2 100644
--- a/test/sun/security/validator/samedn.sh
+++ b/test/sun/security/validator/samedn.sh
@@ -48,7 +48,7 @@
esac
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit \
- -keypass changeit -keystore samedn.jks"
+ -keypass changeit -keystore samedn.jks -keyalg rsa"
JAVAC=$COMPILEJAVA${FS}bin${FS}javac
JAVA=$TESTJAVA${FS}bin${FS}java
diff --git a/test/sun/text/resources/LocaleData b/test/sun/text/resources/LocaleData
index 8a717f6..1fd2076 100644
--- a/test/sun/text/resources/LocaleData
+++ b/test/sun/text/resources/LocaleData
@@ -7681,3 +7681,9 @@
# bug 8021121
CurrencyNames/lv_LV/EUR=\u20AC
+
+# bug # 6192407
+LocaleNames/ko/PT=\ud3ec\ub974\ud22c\uce7c
+
+# bug 6931564
+LocaleNames/sv/ZA=Sydafrika
diff --git a/test/sun/text/resources/LocaleDataTest.java b/test/sun/text/resources/LocaleDataTest.java
index 09abf98..8918f1a 100644
--- a/test/sun/text/resources/LocaleDataTest.java
+++ b/test/sun/text/resources/LocaleDataTest.java
@@ -35,7 +35,7 @@
* 6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 6916787
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
- * 7114053 7074882 7040556 8013836 8021121
+ * 7114053 7074882 7040556 8013836 8021121 6192407 6931564
* @summary Verify locale data
*
*/
diff --git a/test/sun/tools/jstatd/JstatGCUtilParser.java b/test/sun/tools/jstatd/JstatGCUtilParser.java
new file mode 100644
index 0000000..217d265
--- /dev/null
+++ b/test/sun/tools/jstatd/JstatGCUtilParser.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.util.Arrays;
+
+import jdk.testlibrary.Utils;
+import static jdk.testlibrary.Asserts.*;
+
+/**
+ * The helper class for parsing following output from command 'jstat -gcutil':
+ *
+ * S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
+ * 100.00 0.00 64.68 13.17 73.39 33.46 2 0.003 1 0.156 0.158
+ * 100.00 0.00 76.54 13.17 73.39 33.46 2 0.003 1 0.156 0.158
+ * 100.00 0.00 83.49 13.17 73.39 33.46 2 0.003 1 0.156 0.158
+ * 100.00 0.00 84.53 13.17 73.39 33.46 2 0.003 1 0.156 0.158
+ * 100.00 0.00 85.57 13.17 73.39 33.46 2 0.003 1 0.156 0.158
+ *
+ * It will be verified that numerical values have defined types and are reasonable,
+ * for example percentage should fit within 0-100 interval.
+ */
+public class JstatGCUtilParser {
+
+ public enum GcStatisticsType {
+ INTEGER, DOUBLE, PERCENTAGE, PERCENTAGE_OR_DASH;
+ }
+
+ public enum GcStatistics {
+ S0(GcStatisticsType.PERCENTAGE),
+ S1(GcStatisticsType.PERCENTAGE),
+ E(GcStatisticsType.PERCENTAGE),
+ O(GcStatisticsType.PERCENTAGE),
+ M(GcStatisticsType.PERCENTAGE),
+ CCS(GcStatisticsType.PERCENTAGE_OR_DASH),
+ YGC(GcStatisticsType.INTEGER),
+ YGCT(GcStatisticsType.DOUBLE),
+ FGC(GcStatisticsType.INTEGER),
+ FGCT(GcStatisticsType.DOUBLE),
+ GCT(GcStatisticsType.DOUBLE);
+
+ private final GcStatisticsType type;
+
+ private GcStatistics(GcStatisticsType type) {
+ this.type = type;
+ }
+
+ private GcStatisticsType getType() {
+ return type;
+ }
+
+ public static boolean isHeadline(String... valueArray) {
+ if (valueArray.length != values().length) {
+ return false;
+ }
+ int headersCount = 0;
+ for (int i = 0; i < values().length; i++) {
+ if (valueArray[i].equals(values()[i].toString())) {
+ headersCount++;
+ }
+ }
+ if (headersCount != values().length) {
+ return false;
+ }
+ return true;
+ }
+
+ private static void verifyLength(String... valueArray) throws Exception {
+ assertEquals(valueArray.length, values().length,
+ "Invalid number of data columns: " + Arrays.toString(valueArray));
+ }
+
+ public static void verify(String... valueArray) throws Exception {
+ verifyLength(valueArray);
+ for (int i = 0; i < values().length; i++) {
+ GcStatisticsType type = values()[i].getType();
+ String value = valueArray[i].trim();
+ if (type.equals(GcStatisticsType.INTEGER)) {
+ Integer.parseInt(value);
+ break;
+ }
+ if (type.equals(GcStatisticsType.DOUBLE)) {
+ Double.parseDouble(value);
+ break;
+ }
+ if (type.equals(GcStatisticsType.PERCENTAGE_OR_DASH) &&
+ value.equals("-")) {
+ break;
+ }
+ double percentage = Double.parseDouble(value);
+ assertTrue(0 <= percentage && percentage <= 100,
+ "Not a percentage: " + value);
+ }
+ }
+
+ }
+
+ private final String output;
+
+ public JstatGCUtilParser(String output) {
+ this.output = output;
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ /**
+ * The function will discard any lines that come before the header line.
+ * This can happen if the JVM outputs a warning message for some reason
+ * before running jstat.
+ */
+ public void parse(int samples) throws Exception {
+ boolean headlineFound = false;
+ int datalineCount = 0;
+
+ String[] lines = output.split(Utils.NEW_LINE);
+ for (String line : lines) {
+ line = line.replaceAll("\\s+", " ").trim();
+ String[] valueArray = line.split(" ");
+
+ if (!headlineFound) {
+ headlineFound = GcStatistics.isHeadline(valueArray);
+ continue;
+ }
+
+ GcStatistics.verify(valueArray);
+ datalineCount++;
+ }
+
+ assertTrue(headlineFound, "No or invalid headline found, expected: " +
+ Utils.NEW_LINE + Arrays.toString(GcStatistics.values()).replaceAll(",", " "));
+ assertEquals(samples, datalineCount,
+ "Expected " + samples + " samples, got " + datalineCount);
+ }
+
+}
diff --git a/test/sun/tools/jstatd/JstatdTest.java b/test/sun/tools/jstatd/JstatdTest.java
new file mode 100644
index 0000000..9876a54
--- /dev/null
+++ b/test/sun/tools/jstatd/JstatdTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.net.UnknownHostException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Arrays;
+
+import static jdk.testlibrary.Asserts.*;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessThread;
+import jdk.testlibrary.TestThread;
+import jdk.testlibrary.Utils;
+
+/**
+ * The base class for tests of jstatd.
+ *
+ * The test sequence for TestJstatdDefaults for example is:
+ * <pre>
+ * {@code
+ * // start jstatd process
+ * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
+ *
+ * // run jps and verify its output
+ * jps -J-XX:+UsePerfData hostname
+ *
+ * // run jstat and verify its output
+ * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 5
+ *
+ * // stop jstatd process and verify that no unexpected exceptions have been thrown
+ * }
+ * </pre>
+ */
+public final class JstatdTest {
+
+ /**
+ * jstat gcutil option: takes JSTAT_GCUTIL_SAMPLES samples at
+ * JSTAT_GCUTIL_INTERVAL_MS millisecond intervals
+ */
+ private static final int JSTAT_GCUTIL_SAMPLES = 5;
+ private static final int JSTAT_GCUTIL_INTERVAL_MS = 250;
+ private static final String JPS_OUTPUT_REGEX = "^\\d+\\s*.*";
+
+ private boolean useDefaultPort = true;
+ private String port;
+ private String serverName;
+ private String jstatdPid;
+ private boolean withExternalRegistry = false;
+
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public void setUseDefaultPort(boolean useDefaultPort) {
+ this.useDefaultPort = useDefaultPort;
+ }
+
+ public void setWithExternalRegistry(boolean withExternalRegistry) {
+ this.withExternalRegistry = withExternalRegistry;
+ }
+
+ /**
+ * Parse pid from jps output
+ */
+ private String parsePid(String tool, OutputAnalyzer output) throws Exception {
+ String[] lines = output.getOutput().split(Utils.NEW_LINE);
+ String pid = null;
+ int count = 0;
+ String processName = tool;
+ if (tool == "rmiregistry") {
+ processName = "registryimpl";
+ }
+ for (String line : lines) {
+ if (line.toLowerCase().matches("^\\d+\\s{1}" + processName + "$")) {
+ pid = line.split(" ")[0];
+ count++;
+ }
+ }
+ if (count > 1) {
+ throw new Exception("Expected one " + tool
+ + " process, got " + count + ". Test will be canceled.");
+ }
+
+ return pid;
+ }
+
+ private String getToolPid(String tool)
+ throws Exception {
+ OutputAnalyzer output = runJps();
+ return parsePid(tool, output);
+ }
+
+ private String waitOnTool(String tool, TestThread thread) throws Throwable {
+ while (true) {
+ String pid = getToolPid(tool);
+
+ if (pid != null) {
+ System.out.println(tool + " pid: " + pid);
+ return pid;
+ }
+
+ Throwable t = thread.getUncaught();
+ if (t != null) {
+ if (t.getMessage().contains(
+ "java.rmi.server.ExportException: Port already in use")) {
+ System.out.println("Port already in use. Trying to restart with a new one...");
+ Thread.sleep(100);
+ return null;
+ } else {
+ // Something unexpected has happened
+ throw new Throwable(t);
+ }
+ }
+
+ System.out.println("Waiting until " + tool + " is running...");
+ Thread.sleep(100);
+ }
+ }
+
+ private void log(String caption, String... cmd) {
+ System.out.println(Utils.NEW_LINE + caption + ":");
+ System.out.println(Arrays.toString(cmd).replace(",", ""));
+ }
+
+ private String getDestination() throws UnknownHostException {
+ String option = Utils.getHostname();
+ if (port != null) {
+ option += ":" + port;
+ }
+ if (serverName != null) {
+ option += "/" + serverName;
+ }
+ return option;
+ }
+
+ /**
+ * Depending on test settings command line can look like:
+ *
+ * jps -J-XX:+UsePerfData hostname
+ * jps -J-XX:+UsePerfData hostname:port
+ * jps -J-XX:+UsePerfData hostname/serverName
+ * jps -J-XX:+UsePerfData hostname:port/serverName
+ */
+ private OutputAnalyzer runJps() throws Exception {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps");
+ launcher.addVMArg("-XX:+UsePerfData");
+ launcher.addToolArg(getDestination());
+
+ String[] cmd = launcher.getCommand();
+ log("Start jps", cmd);
+
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd);
+ OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
+ System.out.println(output.getOutput());
+
+ return output;
+ }
+
+ /**
+ * Verifies output form jps contains pids and programs' name information.
+ * The function will discard any lines that come before the first line with pid.
+ * This can happen if the JVM outputs a warning message for some reason
+ * before running jps.
+ *
+ * The output can look like:
+ * 35536 Jstatd
+ * 35417 Main
+ * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
+ */
+ private void verifyJpsOutput(OutputAnalyzer output) throws Exception {
+ output.shouldHaveExitValue(0);
+ assertFalse(output.getOutput().isEmpty(), "Output should not be empty");
+
+ boolean foundFirstLineWithPid = false;
+ String[] lines = output.getOutput().split(Utils.NEW_LINE);
+ for (String line : lines) {
+ if (!foundFirstLineWithPid) {
+ foundFirstLineWithPid = line.matches(JPS_OUTPUT_REGEX);
+ continue;
+ }
+ assertTrue(line.matches(JPS_OUTPUT_REGEX),
+ "Output does not match the pattern" + Utils.NEW_LINE + line);
+ }
+ assertTrue(foundFirstLineWithPid, "Invalid output");
+ }
+
+ /**
+ * Depending on test settings command line can look like:
+ *
+ * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 5
+ * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port 250 5
+ * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname/serverName 250 5
+ * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port/serverName 250 5
+ */
+ private OutputAnalyzer runJstat() throws Exception {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstat");
+ launcher.addVMArg("-XX:+UsePerfData");
+ launcher.addVMArg("-Duser.language=en");
+ launcher.addToolArg("-gcutil");
+ launcher.addToolArg(jstatdPid + "@" + getDestination());
+ launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_INTERVAL_MS));
+ launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_SAMPLES));
+
+ String[] cmd = launcher.getCommand();
+ log("Start jstat", cmd);
+
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd);
+ OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
+ System.out.println(output.getOutput());
+
+ return output;
+ }
+
+ private void verifyJstatOutput(OutputAnalyzer output)
+ throws Exception {
+ output.shouldHaveExitValue(0);
+ assertFalse(output.getOutput().isEmpty(), "Output should not be empty");
+
+ JstatGCUtilParser gcUtilParser = new JstatGCUtilParser(
+ output.getOutput());
+ gcUtilParser.parse(JSTAT_GCUTIL_SAMPLES);
+ }
+
+ private void runToolsAndVerify() throws Exception {
+ OutputAnalyzer output = runJps();
+ verifyJpsOutput(output);
+
+ output = runJstat();
+ verifyJstatOutput(output);
+ }
+
+ private Registry startRegistry()
+ throws InterruptedException, RemoteException {
+ Registry registry = null;
+ try {
+ System.out.println("Start rmiregistry on port " + port);
+ registry = LocateRegistry
+ .createRegistry(Integer.parseInt(port));
+ } catch (RemoteException e) {
+ if (e.getMessage().contains("Port already in use")) {
+ System.out.println("Port already in use. Trying to restart with a new one...");
+ Thread.sleep(100);
+ return null;
+ } else {
+ throw e;
+ }
+ }
+ return registry;
+ }
+
+ private void cleanUpThread(ProcessThread thread) throws Throwable {
+ if (thread != null) {
+ thread.stopProcess();
+ thread.joinAndThrow();
+ }
+ }
+
+ /**
+ * Depending on test settings command line can look like:
+ *
+ * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
+ * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port
+ * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -n serverName
+ * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port -n serverName
+ */
+ private String[] getJstatdCmd() throws UnknownHostException {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");
+ launcher.addVMArg("-XX:+UsePerfData");
+ String testSrc = System.getProperty("test.src");
+ File policy = new File(testSrc, "all.policy");
+ launcher.addVMArg("-Djava.security.policy=" + policy.getAbsolutePath());
+ if (port != null) {
+ launcher.addToolArg("-p");
+ launcher.addToolArg(port);
+ }
+ if (serverName != null) {
+ launcher.addToolArg("-n");
+ launcher.addToolArg(serverName);
+ }
+
+ String[] cmd = launcher.getCommand();
+ log("Start jstatd", cmd);
+ return cmd;
+ }
+
+ private ProcessThread tryToSetupJstatdProcess() throws Throwable {
+ ProcessThread jstatdThread = new ProcessThread("Jstatd-Thread",
+ getJstatdCmd());
+ try {
+ jstatdThread.start();
+ // Make sure jstatd is up and running
+ jstatdPid = waitOnTool("jstatd", jstatdThread);
+ if (jstatdPid == null) {
+ // The port is already in use. Cancel and try with new one.
+ jstatdThread.stopProcess();
+ jstatdThread.join();
+ return null;
+ }
+ } catch (Throwable t) {
+ // Something went wrong in the product - clean up!
+ cleanUpThread(jstatdThread);
+ throw t;
+ }
+
+ return jstatdThread;
+ }
+
+ public void doTest() throws Throwable {
+ ProcessThread jstatdThread = null;
+ try {
+ while (jstatdThread == null) {
+ if (!useDefaultPort || withExternalRegistry) {
+ port = Integer.toString(Utils.getFreePort());
+ }
+
+ if (withExternalRegistry) {
+ Registry registry = startRegistry();
+ if (registry == null) {
+ // The port is already in use. Cancel and try with new one.
+ continue;
+ }
+ }
+
+ jstatdThread = tryToSetupJstatdProcess();
+ }
+
+ runToolsAndVerify();
+ } finally {
+ cleanUpThread(jstatdThread);
+ }
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdDefaults.java b/test/sun/tools/jstatd/TestJstatdDefaults.java
new file mode 100644
index 0000000..d68f384
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdDefaults.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 4990825
+ * @library /lib/testlibrary
+ * @build JstatdTest JstatGCUtilParser
+ * @run main/timeout=60 TestJstatdDefaults
+ */
+public class TestJstatdDefaults {
+
+ public static void main(String[] args) throws Throwable {
+ JstatdTest test = new JstatdTest();
+ test.doTest();
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdExternalRegistry.java b/test/sun/tools/jstatd/TestJstatdExternalRegistry.java
new file mode 100644
index 0000000..da81db1
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdExternalRegistry.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 4990825 7092186
+ * @library /lib/testlibrary
+ * @build JstatdTest JstatGCUtilParser
+ * @run main/timeout=60 TestJstatdExternalRegistry
+ */
+public class TestJstatdExternalRegistry {
+
+ public static void main(String[] args) throws Throwable {
+ JstatdTest test = new JstatdTest();
+ test.setWithExternalRegistry(true);
+ test.doTest();
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdPort.java b/test/sun/tools/jstatd/TestJstatdPort.java
new file mode 100644
index 0000000..f2d479b
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdPort.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 4990825
+ * @library /lib/testlibrary
+ * @build JstatdTest JstatGCUtilParser
+ * @run main/timeout=60 TestJstatdPort
+ */
+public class TestJstatdPort {
+
+ public static void main(String[] args) throws Throwable {
+ JstatdTest test = new JstatdTest();
+ test.setUseDefaultPort(false);
+ test.doTest();
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdPortAndServer.java b/test/sun/tools/jstatd/TestJstatdPortAndServer.java
new file mode 100644
index 0000000..e771561
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdPortAndServer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 4990825
+ * @library /lib/testlibrary
+ * @build JstatdTest JstatGCUtilParser
+ * @run main/timeout=60 TestJstatdPortAndServer
+ */
+public class TestJstatdPortAndServer {
+
+ public static void main(String[] args) throws Throwable {
+ JstatdTest test = new JstatdTest();
+ test.setUseDefaultPort(false);
+ test.setServerName("TestJstatdServer");
+ test.doTest();
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdServer.java b/test/sun/tools/jstatd/TestJstatdServer.java
new file mode 100644
index 0000000..f8e87a6
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdServer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 4990825
+ * @library /lib/testlibrary
+ * @build JstatdTest JstatGCUtilParser
+ * @run main/timeout=60 TestJstatdServer
+ */
+public class TestJstatdServer {
+
+ public static void main(String[] args) throws Throwable {
+ JstatdTest test = new JstatdTest();
+ test.setServerName("TestJstatdServer");
+ test.doTest();
+ }
+
+}
diff --git a/test/sun/tools/jstatd/TestJstatdUsage.java b/test/sun/tools/jstatd/TestJstatdUsage.java
new file mode 100644
index 0000000..3fd5efc
--- /dev/null
+++ b/test/sun/tools/jstatd/TestJstatdUsage.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.OutputAnalyzer;
+
+/*
+ * @test
+ * @bug 4990825
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.JDKToolLauncher jdk.testlibrary.OutputAnalyzer
+ * @run main TestJstatdUsage
+ */
+public class TestJstatdUsage {
+
+ public static void main(String[] args) throws Exception {
+ testUsage("-help");
+ testUsage("-?");
+ }
+
+ private static void testUsage(String option) throws Exception {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");
+ launcher.addToolArg(option);
+ ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+ OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
+
+ output.shouldContain("usage: jstatd [-nr] [-p port] [-n rminame]");
+ output.shouldHaveExitValue(1);
+ }
+
+}
diff --git a/test/sun/tools/jstatd/jpsOutput1.awk b/test/sun/tools/jstatd/jpsOutput1.awk
deleted file mode 100644
index 4c25392..0000000
--- a/test/sun/tools/jstatd/jpsOutput1.awk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-BEGIN {
- totallines=0; matched=0
- }
-
-/^[0-9]+ [a-z|A-Z][a-z|A-Z|0-9|\$|\.]*$/ {
- matched++;
- }
-
-/^[0-9]+ -- .*$/ {
- matched++;
- }
-
-/^[0-9]+ $/ {
- matched++;
- }
-
- { totallines++; print $0 }
-
-END {
- if ((totallines > 0) && (matched == totallines)) {
- exit 0
- }
- else {
- exit 1
- }
- }
diff --git a/test/sun/tools/jstatd/jstatGcutilOutput1.awk b/test/sun/tools/jstatd/jstatGcutilOutput1.awk
deleted file mode 100644
index 9456f19..0000000
--- a/test/sun/tools/jstatd/jstatGcutilOutput1.awk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# matching the following output specified as a pattern that verifies
-# that the numerical values conform to a specific pattern, rather than
-# specific values.
-#
-# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
-# 0.00 100.00 56.99 7.81 95.03 87.56 1 0.009 0 0.000 0.009
-# 0.00 100.00 63.64 7.81 95.03 87.56 1 0.009 0 0.000 0.009
-# 0.00 100.00 64.68 7.81 95.03 87.56 1 0.009 0 0.000 0.009
-# 0.00 100.00 65.73 7.81 95.03 87.56 1 0.009 0 0.000 0.009
-# 0.00 100.00 67.22 7.81 95.03 87.56 1 0.009 0 0.000 0.009
-
-BEGIN {
- headerlines=0; datalines=0; totallines=0
- }
-
-/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ {
- headerlines++;
- }
-
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+)|-[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
- datalines++;
- }
-
- { totallines++; print $0 }
-
-END {
- if ((headerlines == 1) && (datalines == 5) && (totallines == 6)) {
- exit 0
- }
- else {
- exit 1
- }
- }
diff --git a/test/sun/tools/jstatd/jstatdDefaults.sh b/test/sun/tools/jstatd/jstatdDefaults.sh
deleted file mode 100644
index 02b12cb..0000000
--- a/test/sun/tools/jstatd/jstatdDefaults.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4990825
-# @run shell/timeout=60 jstatdDefaults.sh
-# @summary Test functionality of 'jstatd &'
-
-. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh
-
-setup
-verify_os
-
-cleanup() {
- kill_proc ${JSTATD_PID}
-}
-
-trap 'cleanup' 0 HUP INT QUIT TERM
-
-JSTATD="${TESTJAVA}/bin/jstatd"
-JPS="${TESTJAVA}/bin/jps"
-JSTAT="${TESTJAVA}/bin/jstat"
-
-HOSTNAME=`uname -n`
-
-JSTATD_OUT="jstatd_$$.out"
-
-${JSTATD} -J-XX:+UsePerfData -J-Djava.security.policy=${TESTSRC}/all.policy 2>&1 > ${JSTATD_OUT} &
-JSTATD_PID=$!
-
-echo "jstatd started as pid ${JSTATD_PID}"
-sleep 3
-
-${JPS} -J-XX:+UsePerfData ${HOSTNAME} 2>&1 | awk -f ${TESTSRC}/jpsOutput1.awk
-
-if [ $? -ne 0 ]
-then
- echo "Output of jps differs from expected output. Failed."
- cleanup
- exit 1
-fi
-
-${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
-RC=$?
-
-if [ ${RC} -ne 0 ]
-then
- echo "jstat output differs from expected output"
-fi
-
-if [ -s ${JSTATD_OUT} ]
-then
- echo "jstatd generated the following, unexpected output:"
- RC=1
-fi
-
-cleanup
-
-exit ${RC}
diff --git a/test/sun/tools/jstatd/jstatdExternalRegistry.sh b/test/sun/tools/jstatd/jstatdExternalRegistry.sh
deleted file mode 100644
index 1773bda..0000000
--- a/test/sun/tools/jstatd/jstatdExternalRegistry.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#
-# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4990825 7092186
-# @run shell/timeout=90 jstatdExternalRegistry.sh
-# @summary Test functionality of 'jstatd -p<port>&' with an external RMI registry
-
-. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh
-
-setup
-verify_os
-
-cleanup() {
- kill_proc ${RMIREGISTRY_PID}
- kill_proc ${JSTATD_PID}
-}
-
-trap 'cleanup' 0 HUP INT QUIT TERM
-
-RMIREGISTRY="${TESTJAVA}/bin/rmiregistry"
-JSTATD="${TESTJAVA}/bin/jstatd"
-JPS="${TESTJAVA}/bin/jps"
-JSTAT="${TESTJAVA}/bin/jstat"
-
-HOSTNAME=`uname -n`
-PORT=`freePort`
-if [ "${PORT}" = "0" ] ; then
- echo "Cannot get free port"
- exit 1
-fi
-
-RMIREGISTRY_OUT="rmiregistry_$$.out"
-JSTATD_OUT="jstatd_$$.out"
-
-${RMIREGISTRY} -J-XX:+UsePerfData ${PORT} > ${RMIREGISTRY_OUT} 2>&1 &
-RMIREGISTRY_PID=$!
-
-echo "rmiregistry started on port ${PORT} as pid ${RMIREGISTRY_PID}"
-sleep 3
-
-${JSTATD} -J-XX:+UsePerfData -J-Djava.security.policy=${TESTSRC}/all.policy -p ${PORT} > ${JSTATD_OUT} 2>&1 &
-JSTATD_PID=$!
-
-echo "jstatd started as pid ${JSTATD_PID}"
-sleep 3
-
-${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT} 2>&1 | awk -f ${TESTSRC}/jpsOutput1.awk
-
-if [ $? -ne 0 ]
-then
- echo "Output of jps differs from expected output. Failed."
- exit 1
-fi
-
-${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
-RC=$?
-
-if [ ${RC} -ne 0 ]
-then
- echo "jstat output differs from expected output"
-fi
-
-if [ -s ${JSTATD_OUT} ]
-then
- echo "jstatd generated unexpected output: see ${JSTATD_OUT}"
- RC=1
-fi
-
-if [ -s ${RMIREGISTRY_OUT} ]
-then
- echo "rmiregistry generated unexpected output: see ${RMIREGISTRY_OUT}"
- RC=1
-fi
-
-exit ${RC}
diff --git a/test/sun/tools/jstatd/jstatdPort.sh b/test/sun/tools/jstatd/jstatdPort.sh
deleted file mode 100644
index 0780ae7..0000000
--- a/test/sun/tools/jstatd/jstatdPort.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4990825
-# @run shell/timeout=60 jstatdPort.sh
-# @summary Test functionality of 'jstatd -p <port>&'
-
-. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh
-
-setup
-verify_os
-
-cleanup() {
- kill_proc ${JSTATD_PID}
-}
-
-trap 'cleanup' 0 HUP INT QUIT TERM
-
-JSTATD="${TESTJAVA}/bin/jstatd"
-JPS="${TESTJAVA}/bin/jps"
-JSTAT="${TESTJAVA}/bin/jstat"
-
-HOSTNAME=`uname -n`
-PORT=`freePort`
-if [ "${PORT}" = "0" ] ; then
- echo "Cannot get free port"
- exit 1
-fi
-
-JSTATD_OUT="jstatd_$$.out"
-
-${JSTATD} -J-XX:+UsePerfData -J-Djava.security.policy=${TESTSRC}/all.policy -p ${PORT} 2>&1 > ${JSTATD_OUT} &
-JSTATD_PID=$!
-
-echo "jstatd started as pid ${JSTATD_PID} on port ${PORT}"
-sleep 3
-
-${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT} 2>&1 | tee jps.out | awk -f ${TESTSRC}/jpsOutput1.awk
-
-if [ $? -ne 0 ]
-then
- echo "Output of jps differs from expected output. Failed."
- cleanup
- exit 1
-fi
-
-${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
-RC=$?
-
-if [ ${RC} -ne 0 ]
-then
- echo "jstat output differs from expected output"
-fi
-
-if [ -s ${JSTATD_OUT} ]
-then
- echo "jstatd generated the following, unexpected output:"
- RC=1
-fi
-
-cleanup
-
-exit ${RC}
diff --git a/test/sun/tools/jstatd/jstatdServerName.sh b/test/sun/tools/jstatd/jstatdServerName.sh
deleted file mode 100644
index 50753d6..0000000
--- a/test/sun/tools/jstatd/jstatdServerName.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4990825
-# @run shell/timeout=90 jstatdServerName.sh
-# @summary Test functionality of 'jstatd -p <port> -n <servername>&'
-
-. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh
-
-setup
-verify_os
-
-cleanup() {
- kill_proc ${JSTATD_1_PID}
- kill_proc ${JSTATD_2_PID}
-}
-
-trap 'cleanup' 0 HUP INT QUIT TERM
-
-JSTATD="${TESTJAVA}/bin/jstatd"
-JPS="${TESTJAVA}/bin/jps"
-JSTAT="${TESTJAVA}/bin/jstat"
-
-HOSTNAME=`uname -n`
-PORT_1=`freePort`
-if [ "${PORT_1}" = "0" ] ; then
- echo "ERROR: No free port"
- exit 1
-fi
-PORT_2=`expr ${PORT_1} '+' 1`
-SERVERNAME="SecondJstatdServer"
-
-JSTATD_1_OUT="jstatd_$$_1.out"
-JSTATD_2_OUT="jstatd_$$_2.out"
-
-${JSTATD} -J-XX:+UsePerfData -J-Djava.security.policy=${TESTSRC}/all.policy -p ${PORT_1} 2>&1 > ${JSTATD_1_OUT} &
-JSTATD_1_PID=$!
-
-echo "first jstatd started as pid ${JSTATD_1_PID} on port ${PORT_1} with default server name"
-sleep 3
-
-${JSTATD} -J-XX:+UsePerfData -J-Djava.security.policy=${TESTSRC}/all.policy -p ${PORT_2} -n ${SERVERNAME} 2>&1 > ${JSTATD_2_OUT} &
-JSTATD_2_PID=$!
-
-echo "second jstatd started as pid ${JSTATD_2_PID} on port ${PORT_2} with name ${SERVERNAME}"
-sleep 3
-
-echo "running: ${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT_1}"
-${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT_1} 2>&1 | awk -f ${TESTSRC}/jpsOutput1.awk
-
-if [ $? -ne 0 ]
-then
- echo "Output of jps differs from expected output. Failed."
- cleanup
- exit 1
-fi
-
-echo "running: ${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT_2}/${SERVERNAME}"
-${JPS} -J-XX:+UsePerfData ${HOSTNAME}:${PORT_2}/${SERVERNAME} 2>&1 | awk -f ${TESTSRC}/jpsOutput1.awk
-
-if [ $? -ne 0 ]
-then
- echo "Output of jps differs from expected output. Failed."
- cleanup
- exit 1
-fi
-
-echo "running: ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5"
-${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
-RC=$?
-
-if [ ${RC} -ne 0 ]
-then
- echo "jstat output differs from expected output"
-fi
-
-echo "running: ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5"
-${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
-RC=$?
-
-if [ ${RC} -ne 0 ]
-then
- echo "jstat output differs from expected output"
-fi
-
-if [ -s ${JSTATD_1_OUT} ]
-then
- echo "first jstatd generated the following, unexpected output:"
- RC=1
-fi
-
-if [ -s ${JSTATD_2_OUT} ]
-then
- echo "second jstatd generated the following, unexpected output:"
- RC=1
-fi
-
-cleanup
-
-exit ${RC}
diff --git a/test/sun/tools/jstatd/jstatdUsage1.sh b/test/sun/tools/jstatd/jstatdUsage1.sh
deleted file mode 100644
index d6543b3..0000000
--- a/test/sun/tools/jstatd/jstatdUsage1.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# 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 4990825
-# @run shell jstatdUsage1.sh
-# @summary Test that output of 'jstatd -help' matches the usage.out file
-
-. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh
-
-setup
-
-JSTATD="${TESTJAVA}/bin/jstatd"
-
-JSTATD_1_OUT="jstatd_$$_1.out"
-JSTATD_2_OUT="jstatd_$$_2.out"
-
-${JSTATD} -? > ${JSTATD_1_OUT} 2>&1
-
-diff -w ${JSTATD_1_OUT} ${TESTSRC}/usage.out
-if [ $? != 0 ]
-then
- echo "Output of jstatd -? differs from expected output. Failed."
- exit 1
-fi
-
-${JSTATD} -help > ${JSTATD_2_OUT} 2>&1
-
-diff -w ${JSTATD_2_OUT} ${TESTSRC}/usage.out
-if [ $? != 0 ]
-then
- echo "Output of jstatd -help differs from expected output. Failed."
- exit 1
-fi
-
-exit 0
diff --git a/test/sun/tools/jstatd/usage.out b/test/sun/tools/jstatd/usage.out
deleted file mode 100644
index 1fd27cb..0000000
--- a/test/sun/tools/jstatd/usage.out
+++ /dev/null
@@ -1 +0,0 @@
-usage: jstatd [-nr] [-p port] [-n rminame]
diff --git a/test/sun/util/resources/TimeZone/Bug6317929.java b/test/sun/util/resources/TimeZone/Bug6317929.java
index 665fdb7..8c74a7d 100644
--- a/test/sun/util/resources/TimeZone/Bug6317929.java
+++ b/test/sun/util/resources/TimeZone/Bug6317929.java
@@ -130,12 +130,12 @@
"(New South Wales)\"");
tzLocale = locales2Test[1];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("\u00d6stliche Normalzeit (New South Wales)"))
+ ("Eastern Normalzeit (Neus\u00fcdwales)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"\u00d6stliche Normalzeit " +
- "(New South Wales)\"");
+ "\"Eastern Normalzeit " +
+ "(Neus\u00fcdwales)\"");
tzLocale = locales2Test[2];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
("Hora est\u00e1ndar Oriental (Nueva Gales del Sur)"))
@@ -154,53 +154,53 @@
"(Nouvelle-Galles du Sud)\"");
tzLocale = locales2Test[4];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("Ora solare dell'Australia orientale (Nuovo Galles del Sud)"))
+ ("Ora standard dell'Australia orientale (Nuovo Galles del Sud)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"Ora solare dell'Australia orientale " +
+ "\"Ora standard dell'Australia orientale " +
"(Nuovo Galles del Sud)\"");
tzLocale = locales2Test[5];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("\u6771\u90e8\u6a19\u6e96\u6642 " +
- "(\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9\u30a6\u30a7\u30fc\u30eb\u30ba)"))
+ ("\u6771\u90E8\u6A19\u6E96\u6642" +
+ "(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9\u30A6\u30A7\u30FC\u30EB\u30BA)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"\u6771\u90e8\u6a19\u6e96\u6642 " +
- "(\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9" +
- "\u30a6\u30a7\u30fc\u30eb\u30ba)\"");
+ "\"\u6771\u90E8\u6A19\u6E96\u6642" +
+ "(\u30CB\u30E5\u30FC\u30B5\u30A6\u30B9" +
+ "\u30A6\u30A7\u30FC\u30EB\u30BA)\"");
tzLocale = locales2Test[6];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("\ub3d9\ubd80 \ud45c\uc900\uc2dc(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)"))
+ ("\uB3D9\uBD80 \uD45C\uC900\uC2DC(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"\ub3d9\ubd80 \ud45c\uc900\uc2dc" +
- "(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)\"");
+ "\"\uB3D9\uBD80 \uD45C\uC900\uC2DC" +
+ "(\uB274\uC0AC\uC6B0\uC2A4\uC6E8\uC77C\uC988)\"");
tzLocale = locales2Test[7];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("Eastern, normaltid (Nya Sydwales)"))
+ ("\u00D6stlig standardtid (New South Wales)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"Eastern, normaltid " +
- "(Nya Sydwales)\"");
+ "\"\u00D6stlig standardtid " +
+ "(New South Wales)\"");
tzLocale = locales2Test[8];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09"))
+ ("\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 (\u65B0\u5357\u5A01\u5C14\u65AF)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4 " +
- "\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09\"");
+ "\"\u4E1C\u90E8\u6807\u51C6\u65F6\u95F4 " +
+ "(\u65B0\u5357\u5A01\u5C14\u65AF)\"");
tzLocale = locales2Test[9];
if (!Currie.getDisplayName(false, TimeZone.LONG, tzLocale).equals
- ("\u6771\u65b9\u6a19\u6e96\u6642\u9593 (\u65b0\u5357\u5a01\u723e\u65af)"))
+ ("\u6771\u90E8\u6A19\u6E96\u6642\u9593 (\u65B0\u5357\u5A01\u723E\u65AF)"))
throw new RuntimeException("\n" + tzLocale + ": LONG, " +
"non-daylight saving name for " +
"Australia/Currie should be " +
- "\"\u6771\u65b9\u6a19\u6e96\u6642\u9593 " +
- "(\u65b0\u5357\u5a01\u723e\u65af)\"");
+ "\"\u6771\u90E8\u6A19\u6E96\u6642\u9593 " +
+ "(\u65B0\u5357\u5A01\u723E\u65AF)\"");
}
}
diff --git a/test/tools/jar/normalize/TestNormal.java b/test/tools/jar/normalize/TestNormal.java
new file mode 100644
index 0000000..7db348c
--- /dev/null
+++ b/test/tools/jar/normalize/TestNormal.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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
+ * @run main/timeout=600 TestNormal
+ * @bug 8020802
+ * @summary Need an ability to create jar files that are invariant to the pack200 packing/unpacking
+ * @author Alexander Zuev
+ */
+
+import java.io.*;
+import java.util.Collections;
+import java.util.Properties;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public class TestNormal {
+ private static String FS = File.separator;
+
+ public static void main(String args[]) throws Exception {
+ Properties p = System.getProperties();
+ String java_home = p.getProperty("test.jdk");
+ String dtjar = java_home + File.separator + "lib"
+ + File.separator + "dt.jar";
+
+ File folder = new File("dt");
+ if (folder.exists()) {
+ delete(folder);
+ }
+ folder.mkdir();
+
+ try {
+ extractJar(new JarFile(dtjar), folder);
+ execJavaCommand(java_home, "jar cnf normalized.jar -C dt .");
+ execJavaCommand(java_home, "jar cf original.jar -C dt .");
+ execJavaCommand(java_home, "pack200 -r repacked.jar original.jar");
+ compareJars(new JarFile("normalized.jar"), new JarFile("repacked.jar"));
+ } finally {
+ String[] cleanupList = {"dt", "normalized.jar", "original.jar", "repacked.jar"};
+ for (String s : cleanupList) {
+ delete(new File(s));
+ }
+ }
+ }
+
+ public static void execJavaCommand(String java_home, String cmd) throws Exception {
+ Process proc = Runtime.getRuntime().exec(java_home + FS + "bin" + FS + cmd);
+ String s;
+ BufferedReader stdInput =
+ new BufferedReader(new InputStreamReader(proc.getInputStream()));
+ BufferedReader stdError =
+ new BufferedReader(new InputStreamReader(proc.getErrorStream()));
+ while ((s = stdInput.readLine()) != null) {
+ System.out.println(s);
+ }
+ while ((s = stdError.readLine()) != null) {
+ System.err.println(s);
+ }
+ }
+
+ public static void compareJars(JarFile jf1, JarFile jf2) throws Exception {
+ try {
+ if (jf1.size() != jf2.size()) {
+ throw new Exception("Jars " + jf1.getName() + " and " + jf2.getName()
+ + " have different number of entries");
+ }
+ for (JarEntry elem1 : Collections.list(jf1.entries())) {
+ JarEntry elem2 = jf2.getJarEntry(elem1.getName());
+ if (elem2 == null) {
+ throw new Exception("Element " + elem1.getName() + " is missing from " + jf2.getName());
+ }
+ if (!elem1.isDirectory() && elem1.getCrc() != elem2.getCrc()) {
+ throw new Exception("The crc of " + elem1.getName() + " is different.");
+ }
+ }
+ } finally {
+ jf1.close();
+ jf2.close();
+ }
+ }
+
+ public static void extractJar(JarFile jf, File where) throws Exception {
+ for (JarEntry file : Collections.list(jf.entries())) {
+ File out = new File(where, file.getName());
+ if (file.isDirectory()) {
+ out.mkdirs();
+ continue;
+ }
+ File parent = out.getParentFile();
+ if (parent != null && !parent.exists()) {
+ parent.mkdirs();
+ }
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ is = jf.getInputStream(file);
+ os = new FileOutputStream(out);
+ while (is.available() > 0) {
+ os.write(is.read());
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ if (os != null) {
+ os.close();
+ }
+ }
+ }
+ }
+
+ static void delete(File f) throws IOException {
+ if (!f.exists()) {
+ return;
+ }
+ if (f.isDirectory()) {
+ for (File c : f.listFiles()) {
+ delete(c);
+ }
+ }
+ if (!f.delete()) {
+ throw new FileNotFoundException("Failed to delete file: " + f);
+ }
+ }
+}
diff --git a/test/tools/launcher/VersionCheck.java b/test/tools/launcher/VersionCheck.java
index 7373ac5..f43c210 100644
--- a/test/tools/launcher/VersionCheck.java
+++ b/test/tools/launcher/VersionCheck.java
@@ -50,6 +50,7 @@
"javaws",
"jcontrol",
"jmc",
+ "jmc.ini",
"jvisualvm",
"packager",
"unpack200",
@@ -74,6 +75,7 @@
"jinfo",
"jmap",
"jmc",
+ "jmc.ini",
"jps",
"jrunscript",
"jjs",