From 2b497d2a1afbd2f1b9775d40020dbbc58fe3a470 Mon Sep 17 00:00:00 2001
From: Vyom Tewari The JNI documents specify that, at least for returning
+ * values from native methods, a Java boolean value is converted
+ * to the value-set 0..1 by first truncating to a byte (0..255 or
+ * maybe -128..127) and then testing against zero. Thus, Java
+ * booleans in non-Java data structures are by convention
+ * represented as 8-bit containers containing either zero (for
+ * false) or any non-zero value (for true).
+ *
+ * Java booleans in the heap are also stored in bytes, but are
+ * strongly normalized to the value-set 0..1 (i.e., they are
+ * truncated to the least-significant bit).
+ *
+ * The main reason for having different conventions for
+ * conversion is performance: Truncation to the least-significant
+ * bit can be usually implemented with fewer (machine)
+ * instructions than byte testing against zero.
+ *
+ * A number of Unsafe methods load boolean values from the heap
+ * as bytes. Unsafe converts those values according to the JNI
+ * rules (i.e, using the "testing against zero" convention). The
+ * method {@code byte2bool} implements that conversion.
+ *
+ * @param b the byte to be converted to boolean
+ * @return the result of the conversion
+ */
@ForceInline
private boolean byte2bool(byte b) {
- return b > 0;
+ return b != 0;
}
+ /**
+ * Convert a boolean value to a byte. The return value is strongly
+ * normalized to the value-set 0..1 (i.e., the value is truncated
+ * to the least-significant bit). See {@link #byte2bool(byte)} for
+ * more details on conversion conventions.
+ *
+ * @param b the boolean to be converted to byte (and then normalized)
+ * @return the result of the conversion
+ */
@ForceInline
private byte bool2byte(boolean b) {
return b ? (byte)1 : (byte)0;
From 00c9b389f60f49dfe43ffc1f4c809507f49d37da Mon Sep 17 00:00:00 2001
From: Zoltan Majo The Common UNIX Printing System (CUPS) Headers are required for building the
OpenJDK on Solaris and Linux. The Solaris header files can be obtained by
- installing the package SFWcups from the Solaris Software Companion
- CD/DVD, these often will be installed into the directory /opt/sfw/cups.
The CUPS header files can always be downloaded from www.cups.org.
diff --git a/README-builds.md b/README-builds.md index bddb467612e..49b9fa4a9f3 100644 --- a/README-builds.md +++ b/README-builds.md @@ -560,8 +560,7 @@ Some of the more commonly used `configure` options are: > The Common UNIX Printing System (CUPS) Headers are required for building the OpenJDK on Solaris and Linux. The Solaris header files can be obtained by - installing the package **SFWcups** from the Solaris Software Companion - CD/DVD, these often will be installed into the directory `/opt/sfw/cups`. + installing the package **print/cups**. > The CUPS header files can always be downloaded from [www.cups.org](http://www.cups.org). diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index b233cdcd433..5ecc4e8687b 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -5095,7 +5095,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1472718471 +DATE_WHEN_GENERATED=1474459654 ############################################################################### # @@ -56909,23 +56909,6 @@ fi done - fi - if test "x$CUPS_FOUND" = xno; then - # Getting nervous now? Lets poke around for standard Solaris third-party - # package installation locations. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cups headers" >&5 -$as_echo_n "checking for cups headers... " >&6; } - if test -s $SYSROOT/opt/sfw/cups/include/cups/cups.h; then - # An SFW package seems to be installed! - CUPS_FOUND=yes - CUPS_CFLAGS="-I$SYSROOT/opt/sfw/cups/include" - elif test -s $SYSROOT/opt/csw/include/cups/cups.h; then - # A CSW package seems to be installed! - CUPS_FOUND=yes - CUPS_CFLAGS="-I$SYSROOT/opt/csw/include" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CUPS_FOUND" >&5 -$as_echo "$CUPS_FOUND" >&6; } fi if test "x$CUPS_FOUND" = xno; then diff --git a/common/autoconf/lib-cups.m4 b/common/autoconf/lib-cups.m4 index 8a61bc04104..0a7df8b381b 100644 --- a/common/autoconf/lib-cups.m4 +++ b/common/autoconf/lib-cups.m4 @@ -75,21 +75,6 @@ AC_DEFUN_ONCE([LIB_SETUP_CUPS], DEFAULT_CUPS=yes ]) fi - if test "x$CUPS_FOUND" = xno; then - # Getting nervous now? Lets poke around for standard Solaris third-party - # package installation locations. - AC_MSG_CHECKING([for cups headers]) - if test -s $SYSROOT/opt/sfw/cups/include/cups/cups.h; then - # An SFW package seems to be installed! - CUPS_FOUND=yes - CUPS_CFLAGS="-I$SYSROOT/opt/sfw/cups/include" - elif test -s $SYSROOT/opt/csw/include/cups/cups.h; then - # A CSW package seems to be installed! - CUPS_FOUND=yes - CUPS_CFLAGS="-I$SYSROOT/opt/csw/include" - fi - AC_MSG_RESULT([$CUPS_FOUND]) - fi if test "x$CUPS_FOUND" = xno; then HELP_MSG_MISSING_DEPENDENCY([cups]) AC_MSG_ERROR([Could not find cups! $HELP_MSG ]) From 731eb07adc327ee14951d06935c04d9c32fa6a36 Mon Sep 17 00:00:00 2001 From: Alan BurlisonPATH./usr/bin/make on Solaris. If your Solaris system
has the software from the Solaris Developer Companion CD installed, you
-should try and use gmake which will be located in either the /usr/bin,
-/opt/sfw/bin or /usr/sfw/bin directory./usr/bin/gmake or /usr/gnu/bin/make.
* Secmod secmod = Secmod.getInstance();
* if (secmod.isInitialized() == false) {
- * secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla");
+ * secmod.initialize("/home/myself/.mozilla");
* }
*
* Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider();
diff --git a/jdk/test/jprt.config b/jdk/test/jprt.config
index 3d6c975a398..9f438197ec3 100644
--- a/jdk/test/jprt.config
+++ b/jdk/test/jprt.config
@@ -82,15 +82,12 @@ if [ "${osname}" = SunOS ] ; then
fi
# Add basic solaris system paths
- path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin
+ path4sdk=/usr/bin:/usr/gnu/bin
# Find GNU make
- make=/usr/sfw/bin/gmake
+ make=/usr/bin/gmake
if [ ! -f ${make} ] ; then
- make=/opt/sfw/bin/gmake
- if [ ! -f ${make} ] ; then
- make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
- fi
+ make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
fi
fileMustExist "${make}" make
diff --git a/jdk/test/start-Xvfb.sh b/jdk/test/start-Xvfb.sh
index ea3d16c9997..ec6a4a2b1c7 100644
--- a/jdk/test/start-Xvfb.sh
+++ b/jdk/test/start-Xvfb.sh
@@ -59,9 +59,6 @@ else
/usr/bin/nohup /usr/bin/X11/Xvfb -fbdir ${currentDir} -pixdepths 8 16 24 32 ${DISPLAY} > ${currentDir}/nohup.$$ 2>&1 &
fi
WM="/usr/bin/X11/fvwm2"
-if [ ! -x ${WM} ] ; then
- WM="/opt/sfw/bin/fvwm2"
-fi
#
# Wait for Xvfb to initialize:
sleep 5
diff --git a/jdk/test/sun/security/smartcardio/README.txt b/jdk/test/sun/security/smartcardio/README.txt
index 5efbb5fa33b..6a0953a61e3 100644
--- a/jdk/test/sun/security/smartcardio/README.txt
+++ b/jdk/test/sun/security/smartcardio/README.txt
@@ -1,17 +1,17 @@
Rough hints for setting up MUSCLE on Solaris:
-Make sure you have libusb, usually in /usr/sfw:
+Make sure you have libusb, usually in /usr/lib:
-ls -l /usr/sfw/lib/libusb.so
-lrwxrwxrwx 1 root other 11 Jan 12 16:02 /usr/sfw/lib/libusb.so -> libusb.so.1
+ls -l /usr/lib/libusb.so
+lrwxrwxrwx 1 root other 11 Jan 12 16:02 /usr/lib/libusb.so -> libusb.so.1
Get PCSC and CCID.
-rwx------ 1 user staff 529540 Jun 16 18:24 ccid-1.0.1.tar.gz
-rwx------ 1 user staff 842654 Jun 16 18:24 pcsc-lite-1.3.1.tar.gz
Unpack pcsc
-Run ./configure --enable-libusb=/usr/sfw (??)
+Run ./configure --enable-libusb (??)
gnumake
Make /usr/local writeable for user
gnumake install
diff --git a/jdk/test/sun/security/tools/keytool/KeyToolTest.java b/jdk/test/sun/security/tools/keytool/KeyToolTest.java
index a783c4e9dbd..7e19d510767 100644
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java
@@ -1761,7 +1761,7 @@ public class KeyToolTest {
//PKCS#11 tests
// 1. sccs edit cert8.db key3.db
- //Runtime.getRuntime().exec("/usr/ccs/bin/sccs edit cert8.db key3.db");
+ //Runtime.getRuntime().exec("/usr/bin/sccs edit cert8.db key3.db");
testOK("", p11Arg + ("-storepass test12 -genkey -alias genkey" +
" -dname cn=genkey -keysize 512 -keyalg rsa"));
testOK("", p11Arg + "-storepass test12 -list");
@@ -1781,7 +1781,7 @@ public class KeyToolTest {
testOK("", p11Arg + "-storepass test12 -list");
assertTrue(out.indexOf("Your keystore contains 0 entries") != -1);
//(check for empty database listing)
- //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db");
+ //Runtime.getRuntime().exec("/usr/bin/sccs unedit cert8.db key3.db");
remove("genkey.cert");
remove("genkey.certreq");
// 12. sccs unedit cert8.db key3.db
diff --git a/jdk/test/tools/launcher/RunpathTest.java b/jdk/test/tools/launcher/RunpathTest.java
index 26233b28561..00e757343c3 100644
--- a/jdk/test/tools/launcher/RunpathTest.java
+++ b/jdk/test/tools/launcher/RunpathTest.java
@@ -40,7 +40,7 @@ public class RunpathTest extends TestHelper {
}
final String findElfReader() {
- String[] paths = {"/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/ccs/bin"};
+ String[] paths = {"/usr/sbin", "/usr/bin"};
final String cmd = isSolaris ? "elfdump" : "readelf";
for (String x : paths) {
File p = new File(x);
From ce5c490b25f3dc274788b8e6917b0004d64117e8 Mon Sep 17 00:00:00 2001
From: Alan Burlison
Date: Wed, 21 Sep 2016 14:23:33 +0200
Subject: [PATCH 058/114] 8165161: Solaris: /usr/ccs /opt/sfw and /opt/csw are
dead, references should be expunged
Reviewed-by: erikj
---
hotspot/test/jprt.config | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hotspot/test/jprt.config b/hotspot/test/jprt.config
index 53ffdaecd83..d6ffc5f070e 100644
--- a/hotspot/test/jprt.config
+++ b/hotspot/test/jprt.config
@@ -86,12 +86,12 @@ case "${osname}" in
fi
# Add basic solaris system paths
- path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin
+ path4sdk=/usr/bin
# Find GNU make
- make=/usr/sfw/bin/gmake
+ make=/usr/bin/gmake
if [ ! -f ${make} ] ; then
- make=/opt/sfw/bin/gmake
+ make=/usr/gnu/bin/make
if [ ! -f ${make} ] ; then
make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
fi
From 1c751c11fb5e54e0a402c5aa098b16290e9182c0 Mon Sep 17 00:00:00 2001
From: Sergei Kovalev
Date: Wed, 21 Sep 2016 17:09:41 +0300
Subject: [PATCH 059/114] 8166450: smartcardio related tests failed on
compilation during execution with jtreg tool
Reviewed-by: weijun
---
jdk/test/sun/security/smartcardio/TestChannel.java | 3 ++-
jdk/test/sun/security/smartcardio/TestConnect.java | 3 ++-
jdk/test/sun/security/smartcardio/TestConnectAgain.java | 3 ++-
jdk/test/sun/security/smartcardio/TestControl.java | 3 ++-
jdk/test/sun/security/smartcardio/TestDefault.java | 3 ++-
jdk/test/sun/security/smartcardio/TestDirect.java | 3 ++-
jdk/test/sun/security/smartcardio/TestExclusive.java | 3 ++-
jdk/test/sun/security/smartcardio/TestMultiplePresent.java | 3 ++-
jdk/test/sun/security/smartcardio/TestPresent.java | 3 ++-
jdk/test/sun/security/smartcardio/TestTransmit.java | 3 ++-
10 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/jdk/test/sun/security/smartcardio/TestChannel.java b/jdk/test/sun/security/smartcardio/TestChannel.java
index c7e022f7c21..90052158ca7 100644
--- a/jdk/test/sun/security/smartcardio/TestChannel.java
+++ b/jdk/test/sun/security/smartcardio/TestChannel.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6239117
* @summary test logical channels work
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestChannel
*/
diff --git a/jdk/test/sun/security/smartcardio/TestConnect.java b/jdk/test/sun/security/smartcardio/TestConnect.java
index 467939e1059..fa0631c98ad 100644
--- a/jdk/test/sun/security/smartcardio/TestConnect.java
+++ b/jdk/test/sun/security/smartcardio/TestConnect.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6293769 6294527 6309280
* @summary test connect() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestConnect
*/
diff --git a/jdk/test/sun/security/smartcardio/TestConnectAgain.java b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
index f4e6af21cba..7f2343b2edd 100644
--- a/jdk/test/sun/security/smartcardio/TestConnectAgain.java
+++ b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6239117
* @summary test connect works correctly if called multiple times/card removed
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestConnectAgain
*/
diff --git a/jdk/test/sun/security/smartcardio/TestControl.java b/jdk/test/sun/security/smartcardio/TestControl.java
index 682f715d1c4..fd1c936582e 100644
--- a/jdk/test/sun/security/smartcardio/TestControl.java
+++ b/jdk/test/sun/security/smartcardio/TestControl.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6239117 6470320
* @summary test if transmitControlCommand() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestControl
*/
diff --git a/jdk/test/sun/security/smartcardio/TestDefault.java b/jdk/test/sun/security/smartcardio/TestDefault.java
index 9f3a6660426..190b988e91b 100644
--- a/jdk/test/sun/security/smartcardio/TestDefault.java
+++ b/jdk/test/sun/security/smartcardio/TestDefault.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6327047
* @summary verify that TerminalFactory.getDefault() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestDefault
*/
diff --git a/jdk/test/sun/security/smartcardio/TestDirect.java b/jdk/test/sun/security/smartcardio/TestDirect.java
index 5c09ea907ab..bddc3093934 100644
--- a/jdk/test/sun/security/smartcardio/TestDirect.java
+++ b/jdk/test/sun/security/smartcardio/TestDirect.java
@@ -21,10 +21,11 @@
* questions.
*/
-/**
+/*
* @test
* @bug 8046343
* @summary Make sure that direct protocol is available
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestDirect
*/
diff --git a/jdk/test/sun/security/smartcardio/TestExclusive.java b/jdk/test/sun/security/smartcardio/TestExclusive.java
index 9e4416ac6d9..cd451321f53 100644
--- a/jdk/test/sun/security/smartcardio/TestExclusive.java
+++ b/jdk/test/sun/security/smartcardio/TestExclusive.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6239117
* @summary verify that beginExclusive()/endExclusive() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestExclusive
*/
diff --git a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
index 15e320d2475..9fd2256bf09 100644
--- a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
+++ b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6239117 6445367
* @summary test that CardTerminals.waitForCard() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestMultiplePresent
*/
diff --git a/jdk/test/sun/security/smartcardio/TestPresent.java b/jdk/test/sun/security/smartcardio/TestPresent.java
index 1f499e97c12..fea98795d75 100644
--- a/jdk/test/sun/security/smartcardio/TestPresent.java
+++ b/jdk/test/sun/security/smartcardio/TestPresent.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6293769 6294527
* @summary test that the isCardPresent()/waitForX() APIs work correctly
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestPresent
*/
diff --git a/jdk/test/sun/security/smartcardio/TestTransmit.java b/jdk/test/sun/security/smartcardio/TestTransmit.java
index 85b32f6dd48..e233a4bb163 100644
--- a/jdk/test/sun/security/smartcardio/TestTransmit.java
+++ b/jdk/test/sun/security/smartcardio/TestTransmit.java
@@ -21,11 +21,12 @@
* questions.
*/
-/**
+/*
* @test
* @bug 6293769 6294527
* @summary test transmit() works
* @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
* @run main/manual TestTransmit
*/
From ed209e2a4834214c83a3b60c1b2155581e991de4 Mon Sep 17 00:00:00 2001
From: Bhavesh Patel
Date: Wed, 21 Sep 2016 18:18:50 -0700
Subject: [PATCH 060/114] 8162363: Tables in javadoc documentation missing row
headers
Reviewed-by: jjg
---
.../formats/html/AbstractMemberWriter.java | 45 +++++++-----
.../html/AnnotationTypeFieldWriterImpl.java | 6 +-
...nnotationTypeOptionalMemberWriterImpl.java | 5 +-
...nnotationTypeRequiredMemberWriterImpl.java | 5 +-
.../doclets/formats/html/ClassUseWriter.java | 8 +--
.../html/ConstantsSummaryWriterImpl.java | 3 +-
.../formats/html/ConstructorWriterImpl.java | 19 ++---
.../formats/html/DeprecatedListWriter.java | 13 ++--
.../formats/html/EnumConstantWriterImpl.java | 14 ++--
.../doclets/formats/html/FieldWriterImpl.java | 5 +-
.../formats/html/HtmlDocletWriter.java | 23 ++++---
.../formats/html/MethodWriterImpl.java | 4 +-
.../formats/html/ModuleIndexWriter.java | 4 +-
.../formats/html/ModuleWriterImpl.java | 38 +++++-----
.../formats/html/NestedClassWriterImpl.java | 10 +--
.../formats/html/PackageIndexWriter.java | 4 +-
.../formats/html/PackageUseWriter.java | 17 ++---
.../formats/html/PackageWriterImpl.java | 4 +-
.../formats/html/PropertyWriterImpl.java | 8 +--
.../formats/html/markup/HtmlStyle.java | 1 -
.../doclets/formats/html/markup/HtmlTree.java | 11 +++
.../doclets/toolkit/resources/stylesheet.css | 24 ++++---
.../TestConstantValuesDriver.java | 28 ++++----
.../TestAnnotationTypes.java | 6 +-
.../doclet/testHeadings/TestHeadings.java | 13 ++--
.../testHtmlTableTags/TestHtmlTableTags.java | 52 +++++++++-----
.../javadoc/doclet/testJavaFX/TestJavaFX.java | 46 ++++++-------
.../TestMemberInheritence.java | 6 +-
.../testMemberSummary/TestMemberSummary.java | 4 +-
.../doclet/testModules/TestModules.java | 22 +++---
.../TestNewLanguageFeatures.java | 69 +++++++++----------
.../TestPackageDeprecation.java | 4 +-
.../doclet/testStylesheet/TestStylesheet.java | 5 +-
.../TestTypeAnnotations.java | 28 ++++----
.../doclet/testUseOption/TestUseOption.java | 16 ++---
35 files changed, 296 insertions(+), 274 deletions(-)
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
index 595d5b45af9..d783fd35f05 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
@@ -424,12 +424,15 @@ public abstract class AbstractMemberWriter {
Content tbody = new HtmlTree(HtmlTag.TBODY);
boolean altColor = true;
for (Element member : deprmembers) {
- HtmlTree td = HtmlTree.TD(HtmlStyle.colOne, getDeprecatedLink(member));
+ HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getDeprecatedLink(member));
+ HtmlTree tr = HtmlTree.TR(thRow);
+ HtmlTree td = new HtmlTree(HtmlTag.TD);
+ td.addStyle(HtmlStyle.colLast);
List extends DocTree> deprTrees = utils.getBlockTags(member, DocTree.Kind.DEPRECATED);
if (!deprTrees.isEmpty()) {
writer.addInlineDeprecatedComment(member, deprTrees.get(0), td);
}
- HtmlTree tr = HtmlTree.TR(td);
+ tr.addContent(td);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
tbody.addContent(tr);
@@ -477,8 +480,9 @@ public abstract class AbstractMemberWriter {
tdFirst.addStyle(HtmlStyle.colFirst);
writer.addSummaryType(this, element, tdFirst);
tr.addContent(tdFirst);
- HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
- tdLast.addStyle(HtmlStyle.colLast);
+ HtmlTree thType = new HtmlTree(HtmlTag.TH);
+ thType.addStyle(HtmlStyle.colSecond);
+ thType.addAttr(HtmlAttr.SCOPE, "row");
if (te != null
&& !utils.isConstructor(element)
&& !utils.isClass(element)
@@ -487,14 +491,17 @@ public abstract class AbstractMemberWriter {
HtmlTree name = new HtmlTree(HtmlTag.SPAN);
name.addStyle(HtmlStyle.typeNameLabel);
name.addContent(name(te) + ".");
- tdLast.addContent(name);
+ thType.addContent(name);
}
addSummaryLink(utils.isClass(element) || utils.isInterface(element)
? LinkInfoImpl.Kind.CLASS_USE
: LinkInfoImpl.Kind.MEMBER,
- te, element, tdLast);
- writer.addSummaryLinkComment(this, element, tdLast);
- tr.addContent(tdLast);
+ te, element, thType);
+ tr.addContent(thType);
+ HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+ tdDesc.addStyle(HtmlStyle.colLast);
+ writer.addSummaryLinkComment(this, element, tdDesc);
+ tr.addContent(tdDesc);
tbody.addContent(tr);
}
table.addContent(tbody);
@@ -557,12 +564,15 @@ public abstract class AbstractMemberWriter {
HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD);
tdSummaryType.addStyle(HtmlStyle.colFirst);
writer.addSummaryType(this, member, tdSummaryType);
- HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
- setSummaryColumnStyle(tdSummary);
- addSummaryLink(tElement, member, tdSummary);
- writer.addSummaryLinkComment(this, member, firstSentenceTags, tdSummary);
HtmlTree tr = HtmlTree.TR(tdSummaryType);
- tr.addContent(tdSummary);
+ HtmlTree thSummaryLink = new HtmlTree(HtmlTag.TH);
+ setSummaryColumnStyleAndScope(thSummaryLink);
+ addSummaryLink(tElement, member, thSummaryLink);
+ tr.addContent(thSummaryLink);
+ HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+ tdDesc.addStyle(HtmlStyle.colLast);
+ writer.addSummaryLinkComment(this, member, firstSentenceTags, tdDesc);
+ tr.addContent(tdDesc);
if (utils.isMethod(member) && !utils.isAnnotationType(member)) {
int methodType = utils.isStatic(member) ? MethodTypes.STATIC.value() :
MethodTypes.INSTANCE.value();
@@ -612,12 +622,13 @@ public abstract class AbstractMemberWriter {
}
/**
- * Set the style for the summary column.
+ * Set the style and scope attribute for the summary column.
*
- * @param tdTree the column for which the style will be set
+ * @param thTree the column for which the style and scope attribute will be set
*/
- public void setSummaryColumnStyle(HtmlTree tdTree) {
- tdTree.addStyle(HtmlStyle.colLast);
+ public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
+ thTree.addStyle(HtmlStyle.colSecond);
+ thTree.addAttr(HtmlAttr.SCOPE, "row");
}
/**
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java
index f0392bcc1db..dd7ed67003c 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java
@@ -25,8 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
-
import java.util.Arrays;
import java.util.List;
@@ -222,9 +220,7 @@ public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter
*/
public List getSummaryTableHeader(Element member) {
List header = Arrays.asList(writer.getModifierTypeHeader(),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Fields"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Fields"), resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java
index 2d493090872..237f443a247 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java
@@ -133,9 +133,8 @@ public class AnnotationTypeOptionalMemberWriterImpl extends
*/
public List getSummaryTableHeader(Element member) {
List header = Arrays.asList(writer.getModifierTypeHeader(),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Annotation_Type_Optional_Member"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Annotation_Type_Optional_Member"),
+ resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
index 3d2d0f8b328..06e4a158a1d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
@@ -25,7 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
import java.util.Arrays;
import java.util.List;
@@ -223,9 +222,7 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
*/
public List getSummaryTableHeader(Element member) {
List header = Arrays.asList(writer.getModifierTypeHeader(),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Annotation_Type_Required_Member"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Annotation_Type_Required_Member"), resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
index 75e1313106a..ac3e677f567 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
@@ -330,8 +330,8 @@ public class ClassUseWriter extends SubWriterHolderWriter {
HtmlTree tr = new HtmlTree(HtmlTag.TR);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
- Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, getPackageLink(pkg));
- tr.addContent(tdFirst);
+ Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getPackageLink(pkg));
+ tr.addContent(thFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
addSummaryComment(pkg, tdLast);
@@ -380,9 +380,9 @@ public class ClassUseWriter extends SubWriterHolderWriter {
* @param contentTree the content tree to which the package use information will be added
*/
protected void addPackageUse(PackageElement pkg, Content contentTree) {
- Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst,
+ Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg))));
- contentTree.addContent(tdFirst);
+ contentTree.addContent(thFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
addSummaryComment(pkg, tdLast);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
index 57ee7012236..887d46fe868 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
@@ -25,7 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
import java.util.*;
import javax.lang.model.element.Modifier;
@@ -332,7 +331,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons
Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY,
member, member.getSimpleName(), false);
Content code = HtmlTree.CODE(nameContent);
- return HtmlTree.TD(code);
+ return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, code);
}
/**
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java
index f5bfb4a39bf..be59ef815c9 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java
@@ -25,13 +25,13 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
import java.util.*;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -168,11 +168,13 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
* {@inheritDoc}
*/
@Override
- public void setSummaryColumnStyle(HtmlTree tdTree) {
- if (foundNonPubConstructor)
- tdTree.addStyle(HtmlStyle.colLast);
- else
- tdTree.addStyle(HtmlStyle.colOne);
+ public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
+ if (foundNonPubConstructor) {
+ thTree.addStyle(HtmlStyle.colSecond);
+ } else {
+ thTree.addStyle(HtmlStyle.colFirst);
+ }
+ thTree.addAttr(HtmlAttr.SCOPE, "row");
}
/**
@@ -267,9 +269,8 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
if (foundNonPubConstructor) {
header.add(resources.getText("doclet.Modifier"));
}
- header.add(resources.getText("doclet.0_and_1",
- resources.getText("doclet.Constructor"),
- resources.getText("doclet.Description")));
+ header.add(resources.getText("doclet.Constructor"));
+ header.add(resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
index 71b7e89e1d4..ef7681cf115 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
@@ -261,14 +261,13 @@ public class DeprecatedListWriter extends SubWriterHolderWriter {
for (DeprElementKind kind : DeprElementKind.values()) {
if (deprapi.hasDocumentation(kind)) {
addAnchor(deprapi, kind, div);
- memberTableSummary =
- configuration.getText("doclet.Member_Table_Summary",
- configuration.getText(getHeadingKey(kind)),
- configuration.getText(getSummaryKey(kind)));
+ memberTableSummary
+ = resources.getText("doclet.Member_Table_Summary",
+ resources.getText(getHeadingKey(kind)),
+ resources.getText(getSummaryKey(kind)));
List memberTableHeader = new ArrayList<>();
- memberTableHeader.add(configuration.getText("doclet.0_and_1",
- configuration.getText(getHeaderKey(kind)),
- configuration.getText("doclet.Description")));
+ memberTableHeader.add(resources.getText(getHeaderKey(kind)));
+ memberTableHeader.add(resources.getText("doclet.Description"));
if (kind == DeprElementKind.PACKAGE)
addPackageDeprecatedAPI(deprapi.getSet(kind),
getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java
index b4f6ccedb99..26a2c264499 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java
@@ -25,8 +25,7 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
-
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -34,6 +33,7 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -214,9 +214,8 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter
*/
@Override
public List getSummaryTableHeader(Element member) {
- List header = Arrays.asList(configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Enum_Constant"),
- configuration.getText("doclet.Description")));
+ List header = Arrays.asList(resources.getText("doclet.Enum_Constant"),
+ resources.getText("doclet.Description"));
return header;
}
@@ -259,8 +258,9 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter
* {@inheritDoc}
*/
@Override
- public void setSummaryColumnStyle(HtmlTree tdTree) {
- tdTree.addStyle(HtmlStyle.colOne);
+ public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
+ thTree.addStyle(HtmlStyle.colFirst);
+ thTree.addAttr(HtmlAttr.SCOPE, "row");
}
/**
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java
index 9afabb7aa7b..9a9c7a9d59a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java
@@ -25,7 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
import java.util.Arrays;
import java.util.List;
@@ -215,9 +214,7 @@ public class FieldWriterImpl extends AbstractMemberWriter
@Override
public List getSummaryTableHeader(Element member) {
List header = Arrays.asList(writer.getModifierTypeHeader(),
- resources.getText("doclet.0_and_1",
- resources.getText("doclet.Field"),
- resources.getText("doclet.Description")));
+ resources.getText("doclet.Field"), resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 0703094fd3f..96a5e887ed6 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -405,7 +405,7 @@ public class HtmlDocletWriter extends HtmlDocWriter {
}
Content classContent = getLink(new LinkInfoImpl(
configuration, LinkInfoImpl.Kind.PACKAGE, te));
- Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
+ Content tdClass = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, classContent);
HtmlTree tr = HtmlTree.TR(tdClass);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
@@ -942,16 +942,20 @@ public class HtmlDocletWriter extends HtmlDocWriter {
Content tr = new HtmlTree(HtmlTag.TR);
final int size = header.size();
Content tableHeader;
- if (size == 1) {
+ if (size == 2) {
tableHeader = new StringContent(header.get(0));
- tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader));
+ tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
+ tableHeader = new StringContent(header.get(1));
+ tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
return tr;
}
for (int i = 0; i < size; i++) {
tableHeader = new StringContent(header.get(i));
- if(i == 0)
+ if (i == 0)
tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
- else if(i == (size - 1))
+ else if (i == 1)
+ tr.addContent(HtmlTree.TH(HtmlStyle.colSecond, scope, tableHeader));
+ else if (i == (size - 1))
tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
else
tr.addContent(HtmlTree.TH(scope, tableHeader));
@@ -1062,13 +1066,16 @@ public class HtmlDocletWriter extends HtmlDocWriter {
boolean altColor = true;
for (Element e : deprPkgs) {
PackageElement pkg = (PackageElement) e;
- HtmlTree td = HtmlTree.TD(HtmlStyle.colOne,
+ HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getPackageLink(pkg, getPackageName(pkg)));
+ HtmlTree tr = HtmlTree.TR(thRow);
+ HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+ tdDesc.addStyle(HtmlStyle.colLast);
List extends DocTree> tags = utils.getDeprecatedTrees(pkg);
if (!tags.isEmpty()) {
- addInlineDeprecatedComment(pkg, tags.get(0), td);
+ addInlineDeprecatedComment(pkg, tags.get(0), tdDesc);
}
- HtmlTree tr = HtmlTree.TR(td);
+ tr.addContent(tdDesc);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
altColor = !altColor;
tbody.addContent(tr);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
index 6c94d1eb3a8..89abfce4ecb 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
@@ -261,9 +261,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
@Override
public List getSummaryTableHeader(Element member) {
List header = Arrays.asList(writer.getModifierTypeHeader(),
- resources.getText("doclet.0_and_1",
- resources.getText("doclet.Method"),
- resources.getText("doclet.Description")));
+ resources.getText("doclet.Method"), resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java
index 866dc2c4382..5ff751d9f0e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java
@@ -159,11 +159,11 @@ public class ModuleIndexWriter extends AbstractModuleIndexWriter {
for (ModuleElement mdle : modules) {
if (!mdle.isUnnamed()) {
Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
- Content tdModule = HtmlTree.TD(HtmlStyle.colFirst, moduleLinkContent);
+ Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
tdSummary.addStyle(HtmlStyle.colLast);
addSummaryComment(mdle, tdSummary);
- HtmlTree tr = HtmlTree.TR(tdModule);
+ HtmlTree tr = HtmlTree.TR(thModule);
tr.addContent(tdSummary);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
index b79ff717281..75ee6180efd 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
@@ -294,11 +294,11 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
public void addRequiresList(ModuleElement.RequiresDirective direct, Content tbody, boolean altColor) {
ModuleElement m = direct.getDependency();
Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName().toString()));
- Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, moduleLinkContent);
+ Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
tdSummary.addStyle(HtmlStyle.colLast);
addSummaryComment(m, tdSummary);
- HtmlTree tr = HtmlTree.TR(tdPackage);
+ HtmlTree tr = HtmlTree.TR(thPackage);
tr.addContent(tdSummary);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
@@ -347,27 +347,27 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
public void addExportedPackagesList(ModuleElement.ExportsDirective direct, Content tbody, boolean altColor) {
PackageElement pkg = direct.getPackage();
Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
- Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, pkgLinkContent);
- HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
- tdModules.addStyle(HtmlStyle.colSecond);
+ Content tdPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
+ HtmlTree thModules = new HtmlTree(HtmlTag.TD);
+ thModules.addStyle(HtmlStyle.colSecond);
List extends ModuleElement> targetModules = direct.getTargetModules();
if (targetModules != null) {
List extends ModuleElement> mElements = direct.getTargetModules();
for (int i = 0; i < mElements.size(); i++) {
if (i > 0) {
- tdModules.addContent(new HtmlTree(HtmlTag.BR));
+ thModules.addContent(new HtmlTree(HtmlTag.BR));
}
ModuleElement m = mElements.get(i);
- tdModules.addContent(new StringContent(m.getQualifiedName().toString()));
+ thModules.addContent(new StringContent(m.getQualifiedName().toString()));
}
} else {
- tdModules.addContent(configuration.getText("doclet.All_Modules"));
+ thModules.addContent(configuration.getText("doclet.All_Modules"));
}
HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
tdSummary.addStyle(HtmlStyle.colLast);
addSummaryComment(pkg, tdSummary);
HtmlTree tr = HtmlTree.TR(tdPackage);
- tr.addContent(tdModules);
+ tr.addContent(thModules);
tr.addContent(tdSummary);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
@@ -428,11 +428,11 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
public void addUsesList(ModuleElement.UsesDirective direct, Content tbody, boolean altColor) {
TypeElement type = direct.getService();
Content typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, type));
- Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, typeLinkContent);
+ Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, typeLinkContent);
HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
tdSummary.addStyle(HtmlStyle.colLast);
addSummaryComment(type, tdSummary);
- HtmlTree tr = HtmlTree.TR(tdPackage);
+ HtmlTree tr = HtmlTree.TR(thPackage);
tr.addContent(tdSummary);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
@@ -463,18 +463,18 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
TypeElement srv = direct.getService();
Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
- HtmlTree tdType = HtmlTree.TD(HtmlStyle.colFirst, srvLinkContent);
- tdType.addContent(new HtmlTree(HtmlTag.BR));
- tdType.addContent("(");
+ HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
+ thType.addContent(new HtmlTree(HtmlTag.BR));
+ thType.addContent("(");
HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
- tdType.addContent(implSpan);
- tdType.addContent(Contents.SPACE);
- tdType.addContent(implLinkContent);
- tdType.addContent(")");
+ thType.addContent(implSpan);
+ thType.addContent(Contents.SPACE);
+ thType.addContent(implLinkContent);
+ thType.addContent(")");
HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
tdDesc.addStyle(HtmlStyle.colLast);
addSummaryComment(srv, tdDesc);
- HtmlTree tr = HtmlTree.TR(tdType);
+ HtmlTree tr = HtmlTree.TR(thType);
tr.addContent(tdDesc);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
index f43f53eb39a..4c34b2ec9df 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
@@ -25,8 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
-
import java.util.Arrays;
import java.util.List;
@@ -118,15 +116,11 @@ public class NestedClassWriterImpl extends AbstractMemberWriter
public List getSummaryTableHeader(Element member) {
if (utils.isInterface(member)) {
return Arrays.asList(writer.getModifierTypeHeader(),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Interface"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Interface"), resources.getText("doclet.Description"));
} else {
return Arrays.asList(writer.getModifierTypeHeader(),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Class"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Class"), resources.getText("doclet.Description"));
}
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java
index f9c0d3b3613..f6360804701 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java
@@ -151,11 +151,11 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter {
if (!pkg.isUnnamed()) {
if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
- Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent);
+ Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, packageLinkContent);
HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
tdSummary.addStyle(HtmlStyle.colLast);
addSummaryComment(pkg, tdSummary);
- HtmlTree tr = HtmlTree.TR(tdPackage);
+ HtmlTree tr = HtmlTree.TR(thPackage);
tr.addContent(tdSummary);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
tbody.addContent(tr);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
index 05b966ec318..726c64ff927 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
@@ -187,9 +187,7 @@ public class PackageUseWriter extends SubWriterHolderWriter {
*/
protected void addClassList(Content contentTree) {
List classTableHeader = Arrays.asList(
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Class"),
- configuration.getText("doclet.Description")));
+ resources.getText("doclet.Class"), resources.getText("doclet.Description"));
for (String packageName : usingPackageToUsedClasses.keySet()) {
PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName);
HtmlTree li = new HtmlTree(HtmlTag.LI);
@@ -234,10 +232,13 @@ public class PackageUseWriter extends SubWriterHolderWriter {
DocPath dp = pathString(usedClass,
DocPaths.CLASS_USE.resolve(DocPath.forName(utils, usedClass)));
StringContent stringContent = new StringContent(utils.getSimpleName(usedClass));
- Content td = HtmlTree.TD(HtmlStyle.colOne,
+ Content thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getHyperLink(dp.fragment(getPackageAnchorName(pkg)), stringContent));
- addIndexComment(usedClass, td);
- contentTree.addContent(td);
+ contentTree.addContent(thType);
+ HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+ tdDesc.addStyle(HtmlStyle.colLast);
+ addIndexComment(usedClass, tdDesc);
+ contentTree.addContent(tdDesc);
}
/**
@@ -247,10 +248,10 @@ public class PackageUseWriter extends SubWriterHolderWriter {
* @param contentTree the content tree to which the information will be added
*/
protected void addPackageUse(PackageElement pkg, Content contentTree) {
- Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst,
+ Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
getHyperLink(utils.getPackageName(pkg),
new StringContent(utils.getPackageName(pkg))));
- contentTree.addContent(tdFirst);
+ contentTree.addContent(thFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
if (pkg != null && !pkg.isUnnamed()) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
index f6c2eaba492..e787014a798 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
@@ -229,8 +229,8 @@ public class PackageWriterImpl extends HtmlDocletWriter
}
Content classContent = getLink(new LinkInfoImpl(
configuration, LinkInfoImpl.Kind.PACKAGE, klass));
- Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
- HtmlTree tr = HtmlTree.TR(tdClass);
+ Content thClass = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, classContent);
+ HtmlTree tr = HtmlTree.TR(thClass);
tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
index 24c9f96776c..7538fd6c57a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
@@ -25,8 +25,6 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
-
import java.util.Arrays;
import java.util.List;
@@ -235,10 +233,8 @@ public class PropertyWriterImpl extends AbstractMemberWriter
*/
@Override
public List getSummaryTableHeader(Element member) {
- List header = Arrays.asList(configuration.getText("doclet.Type"),
- configuration.getText("doclet.0_and_1",
- configuration.getText("doclet.Property"),
- configuration.getText("doclet.Description")));
+ List header = Arrays.asList(resources.getText("doclet.Type"),
+ resources.getText("doclet.Property"), resources.getText("doclet.Description"));
return header;
}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
index 3b5de9f4cd4..e6c262d7cfc 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
@@ -48,7 +48,6 @@ public enum HtmlStyle {
classUseContainer,
colFirst,
colLast,
- colOne,
colSecond,
constantsSummary,
constantValuesContainer,
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java
index 2b4e0def4b6..062dccc8e12 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java
@@ -807,6 +807,17 @@ public class HtmlTree extends Content {
return TH(null, scope, body);
}
+ /**
+ * Generates a TH tag with style class, scope attribute and some content.
+ *
+ * @param styleClass style for the tag
+ * @param body content for the tag
+ * @return an HtmlTree object for the TH tag
+ */
+ public static HtmlTree TH_ROW_SCOPE(HtmlStyle styleClass, Content body) {
+ return TH(styleClass, "row", body);
+ }
+
/**
* Generates a TITLE tag with some content.
*
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
index a74bf144c27..99ce43cb68d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
@@ -528,20 +528,23 @@ Table styles
float:left;
}
+.rowColor th, .altColor th {
+ font-weight:normal;
+}
.overviewSummary td, .memberSummary td, .typeSummary td,
.useSummary td, .constantsSummary td, .deprecatedSummary td,
.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td {
text-align:left;
padding:0px 0px 12px 10px;
}
-th.colOne, th.colFirst, th.colSecond, th.colLast, .useSummary th, .constantsSummary th, .packagesSummary th,
-td.colOne, td.colFirst, td.colSecond, td.colLast, .useSummary td, .constantsSummary td {
+th.colFirst, th.colSecond, th.colLast, .useSummary th, .constantsSummary th, .packagesSummary th,
+td.colFirst, td.colSecond, td.colLast, .useSummary td, .constantsSummary td {
vertical-align:top;
padding-right:0px;
padding-top:8px;
padding-bottom:3px;
}
-th.colFirst, th.colSecond, th.colLast, th.colOne, .constantsSummary th, .packagesSummary th {
+th.colFirst, th.colSecond, th.colLast, .constantsSummary th, .packagesSummary th {
background:#dee3e9;
text-align:left;
padding:8px 3px 3px 7px;
@@ -550,10 +553,10 @@ td.colFirst, th.colFirst {
white-space:nowrap;
font-size:13px;
}
-td.colLast, th.colLast {
+td.colSecond, th.colSecond, td.colLast, th.colLast {
font-size:13px;
}
-td.colOne, th.colOne, .constantsSummary th, .packagesSummary th {
+.constantsSummary th, .packagesSummary th {
font-size:13px;
}
.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst,
@@ -567,23 +570,22 @@ td.colOne, th.colOne, .constantsSummary th, .packagesSummary th {
.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th,
.usesSummary td.colFirst, .usesSummary th.colFirst,
.useSummary td.colFirst, .useSummary th.colFirst,
-.overviewSummary td.colOne, .overviewSummary th.colOne,
.memberSummary td.colFirst, .memberSummary th.colFirst,
-.memberSummary td.colOne, .memberSummary th.colOne,
+.memberSummary td.colSecond, .memberSummary th.colSecond,
.typeSummary td.colFirst{
width:25%;
vertical-align:top;
}
-td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colSecond a:link, td.colSecond a:active, td.colSecond a:visited, td.colSecond a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colSecond a:link, td.colSecond a:active, td.colSecond a:visited, td.colSecond a:hover, th.colFirst a:link, th.colFirst a:active, th.colFirst a:visited, th.colFirst a:hover, th.colSecond a:link, th.colSecond a:active, th.colSecond a:visited, th.colSecond a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
font-weight:bold;
}
.tableSubHeadingColor {
background-color:#EEEEFF;
}
-.altColor {
+.altColor, .altColor th {
background-color:#FFFFFF;
}
-.rowColor {
+.rowColor, .rowColor th {
background-color:#EEEEEF;
}
/*
@@ -774,4 +776,4 @@ ul.ui-autocomplete li {
.searchTagHolderResult {
font-style:italic;
font-size:12px;
-}
+}
\ No newline at end of file
diff --git a/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java b/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
index 882e8769281..f94cbc47194 100644
--- a/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
+++ b/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4504730 4526070 5077317
+ * @bug 4504730 4526070 5077317 8162363
* @summary Test the generation of constant-values.html.
* @author jamieh
* @library ../lib
@@ -53,29 +53,29 @@ public class TestConstantValuesDriver extends JavadocTester {
"TEST4PASSES",
"\"<Hello World>\"",
"public static final byte\n" +
- "" +
- "BYTE_MAX_VALUE \n" +
+ "" +
+ "BYTE_MAX_VALUE \n" +
"127 ",
"public static final byte\n" +
- "" +
- "BYTE_MIN_VALUE \n" +
+ "" +
+ "BYTE_MIN_VALUE \n" +
"-127 ",
"public static final char\n" +
- "" +
- "CHAR_MAX_VALUE \n" +
+ "" +
+ "CHAR_MAX_VALUE \n" +
"65535 ",
"public static final double",
- "" +
- "DOUBLE_MAX_VALUE \n" +
+ "" +
+ "DOUBLE_MAX_VALUE \n" +
"1.7976931348623157E308 ",
"public static final double\n" +
- "" +
- "DOUBLE_MIN_VALUE ",
+ "" +
+ "DOUBLE_MIN_VALUE ",
"public static final boolean\n" +
- "" +
- "GOODBYE ",
+ "" +
+ "GOODBYE ",
"public static final boolean\n" +
- "HELLO \n" +
+ "HELLO \n" +
"true "
);
}
diff --git a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
index ac867105ded..0cfe4b0f0e0 100644
--- a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
+++ b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4973609 8015249 8025633 8026567 6469561 8071982
+ * @bug 4973609 8015249 8025633 8026567 6469561 8071982 8162363
* @summary Make sure that annotation types with 0 members does not have
* extra HR tags.
* @author jamieh
@@ -56,9 +56,9 @@ public class TestAnnotationTypes extends JavadocTester {
+ "field.detail\">Field | ",
"",
"Field Summary
",
- "DEFAULT_NAME"
- + " ",
+ + "",
"",
"DEFAULT_NAME
\n"
+ "static final java."
diff --git a/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java b/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java
index e93becd44ae..c7811ce5843 100644
--- a/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java
+++ b/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4905786 6259611
+ * @bug 4905786 6259611 8162363
* @summary Make sure that headings use the TH tag instead of the TD tag.
* @author jamieh
* @library ../lib
@@ -76,7 +76,8 @@ public class TestHeadings extends JavadocTester {
// Class documentation
checkOutput("pkg1/C1.html", true,
"Modifier and Type \n"
- + "Field and Description ",
+ + "Field \n"
+ + "Description ",
"Methods inherited from class java.lang.Object
");
// Class use documentation
@@ -84,17 +85,19 @@ public class TestHeadings extends JavadocTester {
"Package \n"
+ "Description ",
"Modifier and Type \n"
- + "Field and Description ");
+ + "Field \n"
+ + "Description ");
// Deprecated
checkOutput("deprecated-list.html", true,
- "Method and Description ");
+ "Method \n"
+ + "Description ");
// Constant values
checkOutput("constant-values.html", true,
""
+ "Modifier and Type \n"
- + "Constant Field \n"
+ + "Constant Field \n"
+ "Value ");
// Serialized Form
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java b/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
index e11de5b4e4a..87102f2d1f9 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6786688 8008164
+ * @bug 6786688 8008164 8162363
* @summary HTML tables should have table summary, caption and table headers.
* @author Bhavesh Patel
* @library ../lib
@@ -282,25 +282,32 @@ public class TestHtmlTableTags extends JavadocTester {
// Class documentation
checkOutput("pkg1/C1.html", true,
"Modifier and Type \n"
- + "Field and Description ",
+ + "Field \n"
+ + "Description ",
"Modifier and Type \n"
- + "Method and Description ");
+ + "Method \n"
+ + "Description ");
checkOutput("pkg2/C2.html", true,
"Modifier and Type \n"
- + "Class and Description ",
- "Constructor and Description ");
+ + "Class \n"
+ + "Description ",
+ "Constructor \n"
+ + "Description ");
checkOutput("pkg2/C2.ModalExclusionType.html", true,
- "Enum Constant and Description ");
+ "Enum Constant \n"
+ + "Description ");
checkOutput("pkg2/C3.html", true,
"Modifier and Type \n"
- + "Required Element and Description ");
+ + "Required Element \n"
+ + "Description ");
checkOutput("pkg2/C4.html", true,
"Modifier and Type \n"
- + "Optional Element and Description ");
+ + "Optional Element \n"
+ + "Description ");
// Class use documentation
checkOutput("pkg1/class-use/I1.html", true,
@@ -309,43 +316,52 @@ public class TestHtmlTableTags extends JavadocTester {
checkOutput("pkg1/class-use/C1.html", true,
"Modifier and Type \n"
- + "Field and Description ",
+ + "Field \n"
+ + "Description ",
"Modifier and Type \n"
- + "Method and Description ");
+ + "Method \n"
+ + "Description ");
checkOutput("pkg2/class-use/C2.html", true,
"Modifier and Type \n"
- + "Field and Description ",
+ + "Field \n"
+ + "Description ",
"Modifier and Type \n"
- + "Method and Description ");
+ + "Method \n"
+ + "Description ");
checkOutput("pkg2/class-use/C2.ModalExclusionType.html", true,
"Package \n"
+ "Description ",
"Modifier and Type \n"
- + "Method and Description ");
+ + "Method \n"
+ + "Description ");
// Package use documentation
checkOutput("pkg1/package-use.html", true,
"Package \n"
+ "Description ",
- "Class and Description ");
+ "Class \n"
+ + "Description ");
checkOutput("pkg2/package-use.html", true,
"Package \n"
+ "Description ",
- "Class and Description ");
+ "Class \n"
+ + "Description ");
// Deprecated
checkOutput("deprecated-list.html", true,
- "Field and Description ",
- "Method and Description ");
+ "Field \n"
+ + "Description ",
+ "Method \n"
+ + "Description ");
// Constant values
checkOutput("constant-values.html", true,
""
+ "Modifier and Type \n"
- + "Constant Field \n"
+ "Value ");
diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
index b7543b5a6d3..e738b85d0f9 100644
--- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
+++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130
+ * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
* @summary Test of the JavaFX doclet features.
* @author jvalenta
* @library ../lib
@@ -61,19 +61,17 @@ public class TestJavaFX extends JavadocTester {
+ "Gets the value of the property rate.\n"
+ "\n"
+ "- Property description:
",
- ""
- + "rate\n"
- + "Defines the direction/speed at which the "
- + "Timeline is expected to",
+ ""
+ + "rate",
"Default value:",
"Since:\n"
+ "- JavaFX 8.0
",
"Sets the value of the property Property",
"
Gets the value of the property Property",
"Property description:",
- "
"
+ ""
+ ""
- + "setTestMethodProperty() ",
+ + "setTestMethodProperty()",
"isPaused
\n"
+ "public final double isPaused()
\n"
+ "Gets the value of the property paused.");
@@ -152,34 +150,34 @@ public class TestJavaFX extends JavadocTester {
checkOutput("pkg2/Test.html", false, "Property Summary
");
checkOutput("pkg2/Test.html", true,
"Modifier and Type \n"
- + "Method and Description \n"
+ + "Method \n"
+ + "Description \n"
+ "\n"
+ "\n"
+ "<T> java.lang.Object \n"
- + ""
- + ""
- + "alphaProperty(java.util.List<T> foo) \n"
+ + ""
+ + "alphaProperty"
+ + "(java.util.List<T> foo) \n"
+ + " \n"
+ " \n"
+ "\n"
+ "java.lang.Object \n"
- + ""
- + "betaProperty()"
- + " \n"
+ + ""
+ + "betaProperty() \n"
+ + " \n"
+ " \n"
+ "\n"
- + ""
- + "java.util.List<java.util.Set<? super java.lang.Object>>"
+ + "java.util.List<java.util.Set<? super java.lang.Object>>"
+ " \n"
- + ""
- + ""
- + "deltaProperty() \n"
+ + ""
+ + "deltaProperty() \n"
+ + " \n"
+ " \n"
+ "\n"
- + "java.util.List<java.lang.String>"
- + " \n"
- + ""
- + "gammaProperty"
- + "() "
+ + "java.util.List<java.lang.String> \n"
+ + ""
+ + "gammaProperty() \n"
+ + " "
);
}
diff --git a/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java b/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
index 9b1b4257ea8..3ad67a283eb 100644
--- a/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
+++ b/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4638588 4635809 6256068 6270645 8025633 8026567
+ * @bug 4638588 4635809 6256068 6270645 8025633 8026567 8162363
* @summary Test to make sure that members are inherited properly in the Javadoc.
* Verify that inheritence labels are correct.
* @author jamieh
@@ -90,10 +90,10 @@ public class TestMemberInheritence extends JavadocTester {
checkOutput("pkg1/Implementer.html", true,
// ensure the method makes it
"static java.time.Period \n"
- + ""
+ + ""
+ ""
+ "between(java.time.LocalDate startDateInclusive,\n"
- + " java.time.LocalDate endDateExclusive) ",
+ + " java.time.LocalDate endDateExclusive)",
// check the inherited from interfaces
"Methods inherited from interface pkg1.Interface
\n"
diff --git a/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java b/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java
index 4dc5ce53587..560c9f1e138 100644
--- a/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java
+++ b/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4951228 6290760 8025633 8026567 8081854
+ * @bug 4951228 6290760 8025633 8026567 8081854 8162363
* @summary Test the case where the overriden method returns a different
* type than the method in the child class. Make sure the
* documentation is inherited but the return type isn't.
@@ -51,7 +51,7 @@ public class TestMemberSummary extends JavadocTester {
checkOutput("pkg/PublicChild.html", true,
// Check return type in member summary.
"PublicChild\n"
- + ""
+ + ""
+ "returnTypeTest()",
// Check return type in member detail.
"public "
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
index 79e166c9b8f..12703fa145a 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995
+ * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363
* @summary Test modules support in javadoc.
* @author bpatel
* @library ../lib
@@ -397,7 +397,7 @@ public class TestModules extends JavadocTester {
+ "");
checkOutput("module1-summary.html", true,
"\n"
- + "testpkgmdl1 \n"
+ + "testpkgmdl1 \n"
+ "All Modules \n"
+ " \n"
+ " ");
@@ -408,7 +408,7 @@ public class TestModules extends JavadocTester {
+ "");
checkOutput("module1-summary.html", true,
"\n"
- + "module2 \n"
+ + "module2 \n"
+ "\n"
+ "This is a test description for the module2 module.\n"
+ " \n"
@@ -424,8 +424,8 @@ public class TestModules extends JavadocTester {
+ "");
checkOutput("module2-summary.html", true,
" \n"
- + ""
- + "testpkg2mdl2 \n"
+ + ""
+ + "testpkg2mdl2 \n"
+ "module1 \n"
+ " \n"
+ " ");
@@ -436,7 +436,7 @@ public class TestModules extends JavadocTester {
+ "");
checkOutput("module2-summary.html", true,
"\n"
- + "java.base \n"
+ + "java.base \n"
+ " \n"
+ " ");
checkOutput("module2-summary.html", true,
@@ -446,24 +446,24 @@ public class TestModules extends JavadocTester {
+ "");
checkOutput("module2-summary.html", true,
"\n"
- + "TestClassInModule2 \n"
+ + "TestClassInModule2 \n"
+ " \n"
+ " ");
checkOutput("module2-summary.html", true,
"\n"
- + "TestInterfaceInModule2
"
+ "(Implementation: "
+ ""
- + "TestClassInModule2) \n"
+ + "TestClassInModule2)\n"
+ " \n"
+ " Exported Packages \n"
+ "\n"
+ "Package \n"
- + "Module \n"
+ + "Module \n"
+ "Description \n"
+ " ");
checkOutput("module2-summary.html", true,
diff --git a/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java
index 312fcf47839..048c310b0ea 100644
--- a/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java
+++ b/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4789689 4905985 4927164 4827184 4993906 5004549 7025314 7010344 8025633 8026567
+ * @bug 4789689 4905985 4927164 4827184 4993906 5004549 7025314 7010344 8025633 8026567 8162363
* @summary Run Javadoc on a set of source files that demonstrate new
* language features. Check the output to ensure that the new
* language features are properly documented.
@@ -134,7 +134,7 @@ public class TestNewLanguageFeatures extends JavadocTester {
// Method that returns TypeParameters
"E[] \n"
- + ""
+ + ""
+ ""
+ "methodThatReturnsTypeParameterA(E[] e)",
@@ -144,15 +144,15 @@ public class TestNewLanguageFeatures extends JavadocTester {
+ "title=\"type parameter in TypeParameters\">E[] e)\n",
"<T extends java.lang.Object & java.lang.Comparable<? super T>>"
+ "
T \n"
- + ""
+ + ""
+ ""
- + "methodtThatReturnsTypeParametersB(java.util.Collection<? extends T> coll)\n"
- + "Returns TypeParameters\n",
+ + "methodtThatReturnsTypeParametersB(java.util.Collection<? extends T> coll)",
+ "Returns TypeParameters\n",
// Method takes a TypeVariable
"<X extends java.lang.Throwable>
"
+ "E"
+ " \n"
- + ""
+ + ""
+ ""
+ "orElseThrow(java.util.function.Supplier<? extends X> exceptionSupplier)"
);
@@ -219,19 +219,19 @@ public class TestNewLanguageFeatures extends JavadocTester {
+ "package-summary.html\">pkg2 with type parameters of "
+ "type "
+ "Foo ",
- "ClassUseTest1<T extends "
+ "Foo"
+ " & "
- + "Foo2> ",
+ + "Foo2>
",
"Methods in pkg2 with type parameters of "
+ "type Foo ",
- "ClassUseTest1."
+ " ClassUseTest1."
+ "method"
- + "(T t) ",
+ + "(T t)",
"Fields in pkg2 with type parameters of "
+ "type "
@@ -259,20 +259,20 @@ public class TestNewLanguageFeatures extends JavadocTester {
+ "type Foo2 "
+ " ",
- "ClassUseTest1<T extends "
+ "Foo"
+ " & "
- + "Foo2> ",
+ + "Foo2>",
"Methods in pkg2 with type parameters of "
+ "type Foo2 "
+ " ",
- ""
+ " "
+ "ClassUseTest1.method"
- + "(T t) "
+ + "(T t) "
);
// ClassUseTest2: >
@@ -282,20 +282,20 @@ public class TestNewLanguageFeatures extends JavadocTester {
+ "type ParamTest"
+ " ",
- "ClassUseTest2<T extends "
+ ""
+ "ParamTest<"
- + "Foo3>> ",
+ + "Foo3>>",
"Methods in pkg2 with type parameters of "
+ "type ParamTest"
+ " ",
- "ClassUseTest2."
+ " ClassUseTest2."
+ "method"
- + "(T t) ",
+ + "(T t) ",
"Fields in pkg2 declared as ParamTest"
@@ -323,20 +323,20 @@ public class TestNewLanguageFeatures extends JavadocTester {
+ "package-summary.html\">pkg2 with type parameters of "
+ "type "
+ "Foo3 ",
- "ClassUseTest2<T extends "
+ ""
+ "ParamTest<"
- + "Foo3>> ",
+ + "Foo3>>",
"Methods in pkg2 with type parameters of "
+ "type Foo3 "
+ " ",
- "ClassUseTest2."
+ " ClassUseTest2."
+ "method"
- + "(T t) ",
+ + "(T t) ",
"Methods in pkg2 that return types with "
+ "arguments of type ParamTest2"
+ " ",
- "ClassUseTest3<T extends "
+ ""
+ "ParamTest2<java.util.List<? extends "
+ ""
- + "Foo4>>> ",
+ + "Foo4>>>",
"Methods in pkg2 with type parameters of "
+ "type ParamTest2"
+ " ",
- "ClassUseTest3"
+ " ClassUseTest3"
+ ".method(T t) ",
+ + "html#method-T-\">method(T t) ",
"<T extends "
+ "ParamTest2<java.util.List<? extends Foo4 "
+ "",
- "ClassUseTest3<T extends "
+ ""
+ "ParamTest2<java.util.List<? extends "
+ ""
- + "Foo4>>> ",
+ + "Foo4>>>",
"Methods in pkg2 with type parameters of "
+ "type Foo4 ",
- "ClassUseTest3."
+ " ClassUseTest3."
+ "method(T t)"
- + " ",
+ + " ",
"Methods in pkg2 that return types with "
+ "arguments of type \n"
+ "\n"
+ "Modifier and Type \n"
- + "Method and Description \n"
+ + "Method \n"
+ + "Description \n"
+ " \n"
+ "\n"
+ "\n"
+ "void \n"
- + "ClassUseTest3."
+ + " ClassUseTest3."
+ "method(java."
+ "util.Set<Foo4> p) \n"
- + " \n"
- + "",
+ + "class in pkg2\">Foo4> p)",
"Constructor parameters in pkg2 with type arguments "
+ "of type <Unnamed>");
+ "<Unnamed> ");
checkFiles(false,
"pkg1/package-summary.html",
diff --git a/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java
index fc37f6ed400..025bf8a6c95 100644
--- a/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java
+++ b/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261
+ * @bug 4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363
* @summary Run tests on doclet stylesheet.
* @author jamieh
* @library ../lib
@@ -139,9 +139,8 @@ public class TestStylesheet extends JavadocTester {
+ ".packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th,\n"
+ ".usesSummary td.colFirst, .usesSummary th.colFirst,\n"
+ ".useSummary td.colFirst, .useSummary th.colFirst,\n"
- + ".overviewSummary td.colOne, .overviewSummary th.colOne,\n"
+ ".memberSummary td.colFirst, .memberSummary th.colFirst,\n"
- + ".memberSummary td.colOne, .memberSummary th.colOne,\n"
+ + ".memberSummary td.colSecond, .memberSummary th.colSecond,\n"
+ ".typeSummary td.colFirst{\n"
+ " width:25%;\n"
+ " vertical-align:top;\n"
diff --git a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
index 088777b7bad..04f0fd659c0 100644
--- a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
+++ b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8005091 8009686 8025633 8026567 6469562 8071982 8071984
+ * @bug 8005091 8009686 8025633 8026567 6469562 8071982 8071984 8162363
* @summary Make sure that type annotations are displayed correctly
* @author Bhavesh Patel
* @library ../lib
@@ -473,7 +473,7 @@ public class TestTypeAnnotations extends JavadocTester {
+ "\" title=\"annotation in typeannos\">@RepTypeUseB ... vararg)");
checkOutput("typeannos/RepeatingOnField.html", true,
- "(package private) java.lang.Integer\n"
+ "(package private) java.lang.Integer \n"
+ "i1",
@@ -483,7 +483,7 @@ public class TestTypeAnnotations extends JavadocTester {
+ "@RepTypeUseA @RepTypeUseB @RepTypeUseB java.lang.Integer\n"
- + " i2",
"(package private) "
+ "@RepTypeUseB @RepTypeUseB java.lang.Integer"
- + " \n"
+ + " \n"
+ "i3",
"(package private) "
+ "@RepAllContextsB @RepAllContextsB java.lang.Integer"
- + "\n"
+ + " \n"
+ "i4",
"(package private) java.lang.String @RepTypeUseA @RepTypeUseB "
- + "@RepTypeUseB []\n [] \nsa",
@@ -572,8 +572,8 @@ public class TestTypeAnnotations extends JavadocTester {
+ "@RepTypeUseB [] sa");
checkOutput("typeannos/RepeatingOnMethod.html", true,
- "(package private) java.lang.String\n(package private) java.lang.String \n"
+ + "test1()",
"(package private) @RepTypeUseB @RepTypeUseB java.lang.String"
- + "\n "
+ + " \n"
+ "test2"
+ "()",
@@ -592,7 +592,7 @@ public class TestTypeAnnotations extends JavadocTester {
+ "@RepTypeUseA @RepTypeUseB @RepTypeUseB java.lang.String"
- + "\n"
+ + " \n"
+ "test3"
+ "()",
@@ -602,7 +602,7 @@ public class TestTypeAnnotations extends JavadocTester {
+ "@RepAllContextsA @RepAllContextsB "
- + "@RepAllContextsB java.lang.String\n"
+ + "@RepAllContextsB java.lang.String \n"
+ "test4()",
@@ -682,12 +682,12 @@ public class TestTypeAnnotations extends JavadocTester {
checkOutput("typeannos/RepeatingOnTypeParametersBoundsTypeArgumentsOnMethod.html", true,
"(package private) <T> java.lang.String\n"
- + " genericMethod(T t)",
"(package private) <T> java.lang.String \n"
- + "genericMethod2(@RepTypeUseA @RepTypeUseB @RepTypeUseB T t)",
- "(package private) java.lang.String \n"
+ "(package private) java.lang.String \n"
+ "test()",
diff --git a/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java b/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
index 9f79964a3d8..409969beeb5 100644
--- a/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4496290 4985072 7006178 7068595 8016328 8050031 8048351 8081854 8071982
+ * @bug 4496290 4985072 7006178 7068595 8016328 8050031 8048351 8081854 8071982 8162363
* @summary A simple test to ensure class-use files are correct.
* @author jamieh
* @library ../lib
@@ -124,17 +124,17 @@ public class TestUseOption extends JavadocTester {
checkOutput("pkg1/class-use/UsedInterface.html", true,
"Subinterfaces of "
+ "UsedInterface in pkg1",
- "interface \n"
+ " interface \n"
+ "SubInterface<T> "
+ + "title=\"interface in pkg1\">SubInterface<T> "
);
checkOutput("pkg1/class-use/UsedThrowable.html", true,
"Methods in pkg1 that throw "
+ "UsedThrowable",
- "void \nvoid \nC1."
+ "methodInC1ThrowsThrowable"
- + "() "
+ + "() "
);
}
@@ -154,9 +154,9 @@ public class TestUseOption extends JavadocTester {
"- "
);
checkOutput("package-use.html", true,
- "
"
- + "UsedInC ",
- "<Unnamed> \n"
+ ""
+ + "UsedInC ",
+ "<Unnamed> \n"
+ " "
);
}
From 1e18e0dc9f5cd1fc354348317774f8751b7ce9be Mon Sep 17 00:00:00 2001
From: Robert Field
Date: Wed, 21 Sep 2016 23:46:06 -0700
Subject: [PATCH 061/114] 8166400: JShell: friendlier representation of array
values
Reviewed-by: sundar, jlahoda
---
.../execution/DirectExecutionControl.java | 16 ++++++++++++++
.../test/jdk/jshell/SimpleRegressionTest.java | 21 +++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java
index ec54b1c8fa2..56e987ea6c8 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java
@@ -24,6 +24,7 @@
*/
package jdk.jshell.execution;
+import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -200,6 +201,21 @@ public class DirectExecutionControl implements ExecutionControl {
return "\"" + (String) value + "\"";
} else if (value instanceof Character) {
return "'" + value + "'";
+ } else if (value.getClass().isArray()) {
+ String tn = value.getClass().getTypeName();
+ int len = Array.getLength(value);
+ StringBuilder sb = new StringBuilder();
+ sb.append(tn.substring(tn.lastIndexOf('.') + 1, tn.length() - 1));
+ sb.append(len);
+ sb.append("] { ");
+ for (int i = 0; i < len; ++i) {
+ sb.append(valueString(Array.get(value, i)));
+ if (i < len - 1) {
+ sb.append(", ");
+ }
+ }
+ sb.append(" }");
+ return sb.toString();
} else {
return value.toString();
}
diff --git a/langtools/test/jdk/jshell/SimpleRegressionTest.java b/langtools/test/jdk/jshell/SimpleRegressionTest.java
index 70de72c9bbb..063a2335f4b 100644
--- a/langtools/test/jdk/jshell/SimpleRegressionTest.java
+++ b/langtools/test/jdk/jshell/SimpleRegressionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -22,7 +22,7 @@
*/
/*
- * @test 8130450 8158906 8154374
+ * @test 8130450 8158906 8154374 8166400
* @summary simple regression test
* @build KullaTesting TestingInputStream
* @run testng SimpleRegressionTest
@@ -149,4 +149,21 @@ public class SimpleRegressionTest extends KullaTesting {
assertEval("class C {}");
assertEval("C.class.getClassLoader() == Thread.currentThread().getContextClassLoader()", "true");
}
+
+ public void testArayRepresentation() {
+ assertEval("new int[4]", "int[4] { 0, 0, 0, 0 }");
+ assertEval("new int[0]", "int[0] { }");
+ assertEval("new byte[2]", "byte[2] { 0, 0 }");
+ assertEval("new short[] { 1234, 4321 }", "short[2] { 1234, 4321 }");
+ assertEval("new long[] { 123456789 }", "long[1] { 123456789 }");
+ assertEval("new float[] { -23.5645f, 1.0101f }", "float[2] { -23.5645, 1.0101 }");
+ assertEval("new double[] { 1/8, Math.PI }", "double[2] { 0.0, 3.141592653589793 }");
+ assertEval("new String[] { \"hi\", \"low\", null }", "String[3] { \"hi\", \"low\", null }");
+ assertEval("new char[] { 'a', 34, 77 }", "char[3] { 'a', '\"', 'M' }");
+ assertEval("new boolean[] { false, true }", "boolean[2] { false, true }");
+ assertEval("new int[][] { new int[] {44, 55}, new int[] {88,99}}",
+ "int[][2] { int[2] { 44, 55 }, int[2] { 88, 99 } }");
+ assertEval("new Object[] { \"howdy\", new int[] { 33, 44, 55 }, new String[] { \"up\", \"down\" }}",
+ "Object[3] { \"howdy\", int[3] { 33, 44, 55 }, String[2] { \"up\", \"down\" } }");
+ }
}
From 139e60e8e3545180aae685c608c1645a881616de Mon Sep 17 00:00:00 2001
From: Jamil Nimeh
Date: Thu, 22 Sep 2016 07:28:40 -0700
Subject: [PATCH 062/114] 8049516: sun.security.provider.SeedGenerator throws
ArrayIndexOutOfBoundsException
Prevent the latch inside ThreadedSeedGenerator.run() from overflowing into a negative value causing a negative index array lookup.
Reviewed-by: xuelei, weijun
---
.../classes/sun/security/provider/SeedGenerator.java | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
index e72ae9f406c..ac3a9f86a1a 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -344,7 +344,8 @@ abstract class SeedGenerator {
try {
BogusThread bt = new BogusThread();
Thread t = new Thread
- (seedGroup, bt, "SeedGenerator Thread", 0, false);
+ (seedGroup, bt, "SeedGenerator Thread", 0,
+ false);
t.start();
} catch (Exception e) {
throw new InternalError("internal error: " +
@@ -357,7 +358,8 @@ abstract class SeedGenerator {
long startTime = System.nanoTime();
while (System.nanoTime() - startTime < 250000000) {
synchronized(this){};
- latch++;
+ // Mask the sign bit and keep latch non-negative
+ latch = (latch + 1) & 0x1FFFFFFF;
}
// Translate the value using the permutation, and xor
@@ -431,7 +433,7 @@ abstract class SeedGenerator {
// data and using it to mix the trivial permutation.
// It should be evenly distributed. The specific values
// are not crucial to the security of this class.
- private static byte[] rndTab = {
+ private static final byte[] rndTab = {
56, 30, -107, -6, -86, 25, -83, 75, -12, -64,
5, -128, 78, 21, 16, 32, 70, -81, 37, -51,
-43, -46, -108, 87, 29, 17, -55, 22, -11, -111,
From 48490309d8d37afd439ef7f860cfb16149db4c9c Mon Sep 17 00:00:00 2001
From: Sean Coffey
Date: Thu, 22 Sep 2016 17:21:10 +0100
Subject: [PATCH 063/114] 8151832: Improve exception messages in exception
thrown by new JDK 9 code
Reviewed-by: alanb
---
.../classes/java/lang/module/ModuleInfo.java | 22 +++++++++----------
.../classes/java/lang/reflect/Proxy.java | 4 ++--
.../jdk/internal/jimage/BasicImageReader.java | 14 +++++++-----
.../jdk/internal/jimage/ImageHeader.java | 3 ++-
.../jdk/internal/jimage/ImageLocation.java | 11 ++++++----
.../jdk/internal/jimage/ImageStream.java | 4 ++--
.../internal/jimage/ImageStringsReader.java | 8 ++++---
.../jdk/internal/jrtfs/JrtFileSystem.java | 5 +++--
.../classes/jdk/internal/jrtfs/JrtPath.java | 15 ++++++++-----
.../share/classes/jdk/internal/misc/VM.java | 2 +-
.../sun/beans/finder/ConstructorFinder.java | 13 ++++++-----
.../classes/javax/imageio/ImageReader.java | 6 ++---
.../classes/javax/imageio/ImageWriter.java | 6 ++---
13 files changed, 66 insertions(+), 47 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
index db9a3e000b9..1d0e22fec11 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
@@ -664,7 +664,7 @@ final class ModuleInfo {
try {
bb.get(b, off, len);
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -681,7 +681,7 @@ final class ModuleInfo {
int ch = bb.get();
return (ch != 0);
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -690,7 +690,7 @@ final class ModuleInfo {
try {
return bb.get();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -699,7 +699,7 @@ final class ModuleInfo {
try {
return ((int) bb.get()) & 0xff;
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -708,7 +708,7 @@ final class ModuleInfo {
try {
return bb.getShort();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -717,7 +717,7 @@ final class ModuleInfo {
try {
return ((int) bb.getShort()) & 0xffff;
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -726,7 +726,7 @@ final class ModuleInfo {
try {
return bb.getChar();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -735,7 +735,7 @@ final class ModuleInfo {
try {
return bb.getInt();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -744,7 +744,7 @@ final class ModuleInfo {
try {
return bb.getLong();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -753,7 +753,7 @@ final class ModuleInfo {
try {
return bb.getFloat();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
@@ -762,7 +762,7 @@ final class ModuleInfo {
try {
return bb.getDouble();
} catch (BufferUnderflowException e) {
- throw new EOFException();
+ throw new EOFException(e.getMessage());
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
index ba2632b5445..15d41a4101d 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
@@ -597,10 +597,10 @@ public class Proxy implements java.io.Serializable {
private final Module module;
ProxyBuilder(ClassLoader loader, List> interfaces) {
if (!VM.isModuleSystemInited()) {
- throw new InternalError("Proxy is not supported until module system is fully initialzed");
+ throw new InternalError("Proxy is not supported until module system is fully initialized");
}
if (interfaces.size() > 65535) {
- throw new IllegalArgumentException("interface limit exceeded");
+ throw new IllegalArgumentException("interface limit exceeded: " + interfaces.size());
}
Set> refTypes = referencedTypes(loader, interfaces);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
index 07038b9ef5e..10506b7029c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
@@ -186,7 +186,9 @@ public class BasicImageReader implements AutoCloseable {
if (result.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
- throw new IOException("The image file \"" + name + "\" is not the correct version");
+ throw new IOException("The image file \"" + name + "\" is not " +
+ "the correct version. Major: " + result.getMajorVersion() +
+ ". Minor: " + result.getMinorVersion());
}
return result;
@@ -318,11 +320,11 @@ public class BasicImageReader implements AutoCloseable {
private ByteBuffer readBuffer(long offset, long size) {
if (offset < 0 || Integer.MAX_VALUE <= offset) {
- throw new IndexOutOfBoundsException("offset");
+ throw new IndexOutOfBoundsException("Bad offset: " + offset);
}
if (size < 0 || Integer.MAX_VALUE <= size) {
- throw new IndexOutOfBoundsException("size");
+ throw new IndexOutOfBoundsException("Bad size: " + size);
}
if (MAP_ALL) {
@@ -382,11 +384,13 @@ public class BasicImageReader implements AutoCloseable {
long uncompressedSize = loc.getUncompressedSize();
if (compressedSize < 0 || Integer.MAX_VALUE < compressedSize) {
- throw new IndexOutOfBoundsException("Compressed size");
+ throw new IndexOutOfBoundsException(
+ "Bad compressed size: " + compressedSize);
}
if (uncompressedSize < 0 || Integer.MAX_VALUE < uncompressedSize) {
- throw new IndexOutOfBoundsException("Uncompressed size");
+ throw new IndexOutOfBoundsException(
+ "Bad uncompressed size: " + uncompressedSize);
}
if (compressedSize == 0) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
index c4ff85bbfb8..f63665119e2 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
@@ -79,7 +79,8 @@ public final class ImageHeader {
Objects.requireNonNull(buffer);
if (buffer.capacity() != HEADER_SLOTS) {
- throw new InternalError("jimage header not the correct size");
+ throw new InternalError(
+ "jimage header not the correct size: " + buffer.capacity());
}
int magic = buffer.get(0);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
index 16787dad3af..ad0ae42fc3d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
@@ -81,7 +81,8 @@ public class ImageLocation {
}
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
int length = attributeLength(data);
@@ -91,7 +92,7 @@ public class ImageLocation {
value <<= 8;
if (!bytes.hasRemaining()) {
- throw new InternalError("\"Missing jimage attribute datad");
+ throw new InternalError("Missing jimage attribute data");
}
value |= bytes.get() & 0xFF;
@@ -134,7 +135,8 @@ public class ImageLocation {
long getAttribute(int kind) {
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
return attributes[kind];
@@ -142,7 +144,8 @@ public class ImageLocation {
String getAttributeString(int kind) {
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
- throw new InternalError("Invalid jimage attribute kind");
+ throw new InternalError(
+ "Invalid jimage attribute kind: " + kind);
}
return getStrings().get((int)attributes[kind]);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
index 9802afcc93a..774e0e6e62a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
@@ -82,7 +82,7 @@ public class ImageStream {
public void ensure(int needs) {
if (needs < 0) {
- throw new IndexOutOfBoundsException("needs");
+ throw new IndexOutOfBoundsException("Bad value: " + needs);
}
if (needs > buffer.remaining()) {
@@ -106,7 +106,7 @@ public class ImageStream {
public void skip(int n) {
if (n < 0) {
- throw new IndexOutOfBoundsException("n");
+ throw new IndexOutOfBoundsException("skip value = " + n);
}
buffer.position(buffer.position() + n);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
index 382e6b1696b..e4a11cbdc14 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
@@ -151,7 +151,7 @@ public class ImageStringsReader implements ImageStrings {
try {
charsFromMUTF8(chars, bytes, offset, count);
} catch (UTFDataFormatException ex) {
- throw new InternalError("Attempt to convert non modified UTF-8 byte sequence");
+ throw new InternalError("Attempt to convert non modified UTF-8 byte sequence", ex);
}
return new String(chars);
@@ -199,7 +199,8 @@ public class ImageStringsReader implements ImageStrings {
ch = buffer.get();
if ((ch & 0xC0) != 0x80) {
- throw new InternalError("Bad continuation in modified UTF-8 byte sequence");
+ throw new InternalError("Bad continuation in " +
+ "modified UTF-8 byte sequence: " + ch);
}
uch = ((uch & ~mask) << 6) | (ch & 0x3F);
@@ -208,7 +209,8 @@ public class ImageStringsReader implements ImageStrings {
}
if ((uch & 0xFFFF) != uch) {
- throw new InternalError("UTF-32 char in modified UTF-8 byte sequence");
+ throw new InternalError("UTF-32 char in modified UTF-8 " +
+ "byte sequence: " + uch);
}
chars[j++] = (char)uch;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
index cb6c85d11e3..49285b31dfb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
@@ -183,7 +183,7 @@ class JrtFileSystem extends FileSystem {
public PathMatcher getPathMatcher(String syntaxAndInput) {
int pos = syntaxAndInput.indexOf(':');
if (pos <= 0 || pos == syntaxAndInput.length()) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("pos is " + pos);
}
String syntax = syntaxAndInput.substring(0, pos);
String input = syntaxAndInput.substring(pos + 1);
@@ -285,7 +285,8 @@ class JrtFileSystem extends FileSystem {
for (OpenOption option : options) {
Objects.requireNonNull(option);
if (!(option instanceof StandardOpenOption)) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "option class: " + option.getClass());
}
}
if (options.contains(StandardOpenOption.WRITE) ||
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
index cf3bbd8d2d9..f23887cabad 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
@@ -122,7 +122,8 @@ final class JrtPath implements Path {
public final JrtPath getName(int index) {
initOffsets();
if (index < 0 || index >= offsets.length) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("index: " +
+ index + ", offsets length: " + offsets.length);
}
int begin = offsets[index];
int end;
@@ -139,7 +140,9 @@ final class JrtPath implements Path {
initOffsets();
if (beginIndex < 0 || endIndex > offsets.length ||
beginIndex >= endIndex) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "beginIndex: " + beginIndex + ", endIndex: " + endIndex +
+ ", offsets length: " + offsets.length);
}
// starting/ending offsets
int begin = offsets[beginIndex];
@@ -211,7 +214,8 @@ final class JrtPath implements Path {
return o;
}
if (jrtfs != o.jrtfs || isAbsolute() != o.isAbsolute()) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(
+ "Incorrect filesystem or path: " + other);
}
final String tp = this.path;
final String op = o.path;
@@ -366,7 +370,8 @@ final class JrtPath implements Path {
private JrtPath checkPath(Path path) {
Objects.requireNonNull(path);
if (!(path instanceof JrtPath))
- throw new ProviderMismatchException();
+ throw new ProviderMismatchException("path class: " +
+ path.getClass());
return (JrtPath) path;
}
@@ -459,7 +464,7 @@ final class JrtPath implements Path {
}
if (c == '\u0000') {
throw new InvalidPathException(path,
- "Path: nul character not allowed");
+ "Path: NUL character not allowed");
}
to.append(c);
prevC = c;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
index 9fe63d56e5e..695795e4338 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
@@ -50,7 +50,7 @@ public class VM {
public static void initLevel(int value) {
synchronized (lock) {
if (value <= initLevel || value > SYSTEM_BOOTED)
- throw new InternalError();
+ throw new InternalError("Bad level: " + value);
initLevel = value;
lock.notifyAll();
}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
index 984bf8ad239..d0315ada6bf 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
@@ -67,19 +67,22 @@ public final class ConstructorFinder extends AbstractFinder> {
*/
public static Constructor> findConstructor(Class> type, Class>...args) throws NoSuchMethodException {
if (type.isPrimitive()) {
- throw new NoSuchMethodException("Primitive wrapper does not contain constructors");
+ throw new NoSuchMethodException("Primitive wrapper does not contain constructors: "
+ + type.getName());
}
if (type.isInterface()) {
- throw new NoSuchMethodException("Interface does not contain constructors");
+ throw new NoSuchMethodException("Interface does not contain constructors: "
+ + type.getName());
}
if (!FinderUtils.isExported(type)) {
- throw new NoSuchMethodException("Class is not accessible");
+ throw new NoSuchMethodException("Class is not accessible: " + type.getName());
}
if (Modifier.isAbstract(type.getModifiers())) {
- throw new NoSuchMethodException("Abstract class cannot be instantiated");
+ throw new NoSuchMethodException("Abstract class cannot be instantiated: "
+ + type.getName());
}
if (!Modifier.isPublic(type.getModifiers()) || !isPackageAccessible(type)) {
- throw new NoSuchMethodException("Class is not accessible");
+ throw new NoSuchMethodException("Class is not accessible: " + type.getName());
}
PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
Signature signature = new Signature(type, args);
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
index 5f39ea935fa..e17a5f2e796 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
@@ -2461,16 +2461,16 @@ public abstract class ImageReader {
try {
bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Bundle not found!");
+ throw new IllegalArgumentException("Bundle not found!", mre);
}
String warning = null;
try {
warning = bundle.getString(keyword);
} catch (ClassCastException cce) {
- throw new IllegalArgumentException("Resource is not a String!");
+ throw new IllegalArgumentException("Resource is not a String!", cce);
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Resource is missing!");
+ throw new IllegalArgumentException("Resource is missing!", mre);
}
listener.warningOccurred(this, warning);
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
index a9a681ce05f..8723c50773e 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
@@ -1963,16 +1963,16 @@ public abstract class ImageWriter implements ImageTranscoder {
try {
bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Bundle not found!");
+ throw new IllegalArgumentException("Bundle not found!", mre);
}
String warning = null;
try {
warning = bundle.getString(keyword);
} catch (ClassCastException cce) {
- throw new IllegalArgumentException("Resource is not a String!");
+ throw new IllegalArgumentException("Resource is not a String!", cce);
} catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Resource is missing!");
+ throw new IllegalArgumentException("Resource is missing!", mre);
}
listener.warningOccurred(this, imageIndex, warning);
From f16543a919b2bfabf09b7f880463fe2b579ad765 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:12 +0000
Subject: [PATCH 064/114] Added tag jdk-9+137 for changeset 2526d9083e41
---
.hgtags-top-repo | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index e540680549f..a0cde0979fb 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -379,3 +379,4 @@ be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133
065724348690eda41fc69112278d8da6dcde548c jdk-9+134
82b94cb5f342319d2cda77f9fa59703ad7fde576 jdk-9+135
3ec350f5f32af249b59620d7e37b54bdcd77b233 jdk-9+136
+d7f519b004254b19e384131d9f0d0e40e31a0fd3 jdk-9+137
From 7b52c73b39f527ad41d52c015dd856c650a79060 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:12 +0000
Subject: [PATCH 065/114] Added tag jdk-9+137 for changeset 94d6d0f4ced0
---
hotspot/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index d842722fa52..c6f688c2bbd 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -539,3 +539,4 @@ a25e0fb6033245ab075136e744d362ce765464cd jdk-9+133
b8b694c6b4d2ab0939aed7adaf0eec1ac321a085 jdk-9+134
3b1c4562953db47e36b237a500f368d5c9746d47 jdk-9+135
a20da289f646ee44440695b81abc0548330e4ca7 jdk-9+136
+dfcbf839e299e7e2bba1da69bdb347617ea4c7e8 jdk-9+137
From 0ddec1875f41c298c30383758e3230dcaec08dc9 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:12 +0000
Subject: [PATCH 066/114] Added tag jdk-9+137 for changeset 7d79b32d8005
---
corba/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/corba/.hgtags b/corba/.hgtags
index e8dba874e9c..e47bd43b69b 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -379,3 +379,4 @@ f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131
1a497f5ca0cfd88115cc7daa8af8a62b8741caf2 jdk-9+134
094d0db606db976045f594dba47d4593b715cc81 jdk-9+135
aa053a3faf266c12b4fd5272da431a3e08e4a3e3 jdk-9+136
+258cf18fa7fc59359b874f8743b7168dc48baf73 jdk-9+137
From a2aedd4cfcbb217681df765d6b4217f62d43d37c Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:13 +0000
Subject: [PATCH 067/114] Added tag jdk-9+137 for changeset 6de6d5c0e9d5
---
jaxp/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index fa7e108ef76..eb923642658 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -379,3 +379,4 @@ e66cdc2de6b02443911d386fc9217b0d824d0686 jdk-9+130
1c6c21d87aa459d82425e1fddc9ce8647aebde34 jdk-9+134
f695240370c77a25fed88225a392e7d530cb4d78 jdk-9+135
f1eafcb0eb7182b937bc93f214d8cabd01ec4d59 jdk-9+136
+a8d5fe567ae72b4931040e59dd4478363f9004f5 jdk-9+137
From a93882a532efa4de04b408d6f86a8ce0ba59c601 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:14 +0000
Subject: [PATCH 068/114] Added tag jdk-9+137 for changeset c3cde7c41eef
---
jdk/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/jdk/.hgtags b/jdk/.hgtags
index d92b0709299..d64c53cafe8 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -379,3 +379,4 @@ d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132
803adcd526d74ae0b64948d1f8260c2dbe514779 jdk-9+134
021369229cfd0b5feb76834b2ea498f47f43c0f3 jdk-9+135
54c5931849a33a363e03fdffa141503f5cc4779d jdk-9+136
+e72df94364e3686e7d62059ce0d6b187b82da713 jdk-9+137
From 1f29517431730f2da29a5228a6b4cf2790549180 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:14 +0000
Subject: [PATCH 069/114] Added tag jdk-9+137 for changeset 3627d835ccf4
---
jaxws/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 8fceda6eb06..73800b65dcd 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -382,3 +382,4 @@ fe4e11bd2423635dc0f5f5cb9a64eb2f2cce7f4c jdk-9+128
ab1d78d395d4cb8be426ff181211da1a4085cf01 jdk-9+134
22631824f55128a7ab6605493b3001a37af6a168 jdk-9+135
09ec13a99f50a4a346180d1e3b0fd8bc1ee399ce jdk-9+136
+297c16d401c534cb879809d2a746d21ca99d2954 jdk-9+137
From 08cbec9e5377f5c5ab8b0e4faed217bea588cf8f Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:15 +0000
Subject: [PATCH 070/114] Added tag jdk-9+137 for changeset 49af2ecba616
---
langtools/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/langtools/.hgtags b/langtools/.hgtags
index c5fe36cee08..959e99614ce 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -379,3 +379,4 @@ aebfafc43714d5a27d5064d8a0011eaccde633cf jdk-9+131
f08683786207a48b652266b3b7b908e6c863c3fc jdk-9+134
af5eb8f3ffd21288305a54ea177ffad75021a741 jdk-9+135
c8f02f0ecbd7cd6700f47416e4b7e9d5ec20ad77 jdk-9+136
+dd56c243c199a540c9f1fbff4855f0934b32a9d0 jdk-9+137
From d436c124fb89c0fdb28642a91952dd820d58d8f1 Mon Sep 17 00:00:00 2001
From: Lana Steuck
Date: Thu, 22 Sep 2016 16:41:15 +0000
Subject: [PATCH 071/114] Added tag jdk-9+137 for changeset b772c7126f36
---
nashorn/.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 26b80a32770..41633a26b9a 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -370,3 +370,4 @@ ee77c6b3713ab293e027ac3ea1cc16f86dac535f jdk-9+131
e05400ba935753c77697af936db24657eb811022 jdk-9+134
cb00d5ef023a18a66fcb4311ed4474d4145c66e9 jdk-9+135
f11b8f5c4ccbf9c87d283815abac6c0117fba3c0 jdk-9+136
+17ed43add2f9e3528686cd786ae2ed49c8ed36e9 jdk-9+137
From 93c5fec349c1aa153bf2e6eba72df777acee55c8 Mon Sep 17 00:00:00 2001
From: Joe Wang
Date: Thu, 22 Sep 2016 10:17:19 -0700
Subject: [PATCH 072/114] 8166398: CatalogSupport tests need to be fixed
Reviewed-by: dfuchs
---
.../internal/impl/XMLEntityManager.java | 8 ++--
.../internal/xinclude/XIncludeHandler.java | 21 +++++-----
.../jaxp/unittest/catalog/CatalogSupport.java | 21 +++++-----
.../jaxp/unittest/catalog/CatalogSupport.xml | 1 +
.../unittest/catalog/CatalogSupportBase.java | 38 ++++++-------------
.../unittest/catalog/XI_simple4Catalog.xml | 2 +-
.../jaxp/unittest/catalog/XI_test2Catalog.xml | 10 +++++
7 files changed, 46 insertions(+), 55 deletions(-)
create mode 100644 jaxp/test/javax/xml/jaxp/unittest/catalog/XI_test2Catalog.xml
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
index d3b848c9847..5ed41e82fc8 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
@@ -1033,12 +1033,12 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
staxInputSource = new StaxXMLInputSource(xmlInputSource, fISCreatedByResolver);
}
- if (staxInputSource == null) {
+ if (staxInputSource == null && fUseCatalog) {
if (fCatalogFeatures == null) {
fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve);
}
fCatalogFile = fCatalogFeatures.get(Feature.FILES);
- if (fUseCatalog && fCatalogFile != null) {
+ if (fCatalogFile != null) {
try {
if (fCatalogResolver == null) {
fCatalogResolver = CatalogManager.catalogResolver(fCatalogFeatures);
@@ -1133,12 +1133,12 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
xmlInputSource = fEntityResolver.resolveEntity(resourceIdentifier);
}
- if (xmlInputSource == null) {
+ if (xmlInputSource == null && fUseCatalog) {
if (fCatalogFeatures == null) {
fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve);
}
fCatalogFile = fCatalogFeatures.get(Feature.FILES);
- if (fUseCatalog && fCatalogFile != null) {
+ if (fCatalogFile != null) {
/*
since the method can be called from various processors, both
EntityResolver and URIResolver are used to attempt to find
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java
index 3f5410c1741..5efe85f9410 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/xinclude/XIncludeHandler.java
@@ -34,6 +34,8 @@ import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
+import com.sun.org.apache.xerces.internal.parsers.XIncludeParserConfiguration;
+import com.sun.org.apache.xerces.internal.parsers.XPointerParserConfiguration;
import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
import com.sun.org.apache.xerces.internal.util.HTTPInputSource;
import com.sun.org.apache.xerces.internal.util.IntStack;
@@ -129,8 +131,6 @@ import org.xml.sax.InputSource;
public class XIncludeHandler
implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
- public final static String XINCLUDE_DEFAULT_CONFIGURATION =
- "com.sun.org.apache.xerces.internal.parsers.XIncludeParserConfiguration";
public final static String HTTP_ACCEPT = "Accept";
public final static String HTTP_ACCEPT_LANGUAGE = "Accept-Language";
public final static String XPOINTER = "xpointer";
@@ -1624,12 +1624,12 @@ public class XIncludeHandler
includedSource =
fEntityResolver.resolveEntity(resourceIdentifier);
- if (includedSource == null) {
+ if (includedSource == null && fUseCatalog) {
if (fCatalogFeatures == null) {
fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve);
}
fCatalogFile = fCatalogFeatures.get(CatalogFeatures.Feature.FILES);
- if (fUseCatalog && fCatalogFile != null) {
+ if (fCatalogFile != null) {
/*
Although URI entry is preferred for resolving XInclude, system entry
is allowed as well.
@@ -1690,14 +1690,11 @@ public class XIncludeHandler
if ((xpointer != null && fXPointerChildConfig == null)
|| (xpointer == null && fXIncludeChildConfig == null) ) {
- String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
- if (xpointer != null)
- parserName = "com.sun.org.apache.xerces.internal.parsers.XPointerParserConfiguration";
-
- fChildConfig =
- (XMLParserConfiguration)ObjectFactory.newInstance(
- parserName,
- true);
+ if (xpointer == null) {
+ fChildConfig = new XIncludeParserConfiguration();
+ } else {
+ fChildConfig = new XPointerParserConfiguration();
+ }
// use the same symbol table, error reporter, entity resolver, security manager and buffer size.
if (fSymbolTable != null) fChildConfig.setProperty(SYMBOL_TABLE, fSymbolTable);
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
index 792cb13ee89..dc96ce2832e 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java
@@ -32,7 +32,6 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamSource;
-
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
@@ -42,7 +41,7 @@ import org.xml.sax.InputSource;
/**
* @test
- * @bug 8158084 8162438 8162442 8166220
+ * @bug 8158084 8162438 8162442 8166220 8166398
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport
* @run testng/othervm catalog.CatalogSupport
@@ -51,7 +50,7 @@ import org.xml.sax.InputSource;
* A custom resolver is used whether or not there's a Catalog;
* A Catalog is used when there's no custom resolver, and the USE_CATALOG
* is true (which is the case by default).
- */
+*/
/**
* Support Catalog:
@@ -177,13 +176,13 @@ public class CatalogSupport extends CatalogSupportBase {
*/
@DataProvider(name = "data_SAXA")
public Object[][] getDataSAX() {
- String[] systemIds = {"system.xsd"};
- InputSource[] returnValues = {new InputSource(new StringReader(dtd_systemResolved))};
- MyEntityHandler entityHandler = new MyEntityHandler(systemIds, returnValues, elementInSystem);
+ String[] systemIds = {"system.dtd"};
return new Object[][]{
{false, true, xml_catalog, xml_system, new MyHandler(elementInSystem), expectedWCatalog},
- {false, true, xml_catalog, xml_system, entityHandler, expectedWResolver},
- {true, true, xml_catalog, xml_system, entityHandler, expectedWResolver}
+ {false, true, xml_catalog, xml_system, getMyEntityHandler(elementInSystem, systemIds,
+ new InputSource(new StringReader(dtd_systemResolved))), expectedWResolver},
+ {true, true, xml_catalog, xml_system, getMyEntityHandler(elementInSystem, systemIds,
+ new InputSource(new StringReader(dtd_systemResolved))), expectedWResolver}
};
}
@@ -209,7 +208,7 @@ public class CatalogSupport extends CatalogSupportBase {
*/
@DataProvider(name = "data_DOMA")
public Object[][] getDataDOM() {
- String[] systemIds = {"system.xsd"};
+ String[] systemIds = {"system.dtd"};
InputSource[] returnValues = {new InputSource(new StringReader(dtd_systemResolved))};
MyEntityHandler entityHandler = new MyEntityHandler(systemIds, returnValues, elementInSystem);
return new Object[][]{
@@ -230,8 +229,8 @@ public class CatalogSupport extends CatalogSupportBase {
return new Object[][]{
{false, true, xml_catalog, xml_system, null, expectedWCatalog},
- {false, true, xml_catalog, xml_system, null, expectedWResolver},
- {true, true, xml_catalog, xml_system, null, expectedWResolver}
+ {false, true, xml_catalog, xml_system, new MyStaxEntityResolver(), expectedWResolver},
+ {true, true, xml_catalog, xml_system, new MyStaxEntityResolver(), expectedWResolver}
};
}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.xml
index f889ac50a78..63432cb50e8 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.xml
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.xml
@@ -15,6 +15,7 @@
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
index 27bf6b4b661..236e5cda0dc 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
@@ -276,7 +276,7 @@ public class CatalogSupportBase {
SAXParser parser = getSAXParser(setUseCatalog, useCatalog, catalog);
parser.parse(xml, handler);
- assertEquals(expected, handler.getResult().trim(), "");
+ Assert.assertEquals(handler.getResult().trim(), expected);
}
/*
@@ -287,8 +287,9 @@ public class CatalogSupportBase {
XMLReader reader = getXMLReader(setUseCatalog, useCatalog, catalog);
reader.setContentHandler(handler);
+ reader.setEntityResolver(handler);
reader.parse(xml);
- assertEquals(expected, handler.getResult().trim(), "");
+ Assert.assertEquals(handler.getResult().trim(), expected);
}
/*
@@ -300,7 +301,7 @@ public class CatalogSupportBase {
parser.parse(new InputSource(new StringReader(xml)), handler);
debugPrint("handler.result:" + handler.getResult());
- assertEquals(expected, handler.getResult(), "Catalog support for XInclude");
+ Assert.assertEquals(handler.getResult().trim(), expected);
}
/*
@@ -314,8 +315,7 @@ public class CatalogSupportBase {
Node node = doc.getElementsByTagName(elementInSystem).item(0);
String result = node.getFirstChild().getTextContent();
-
- assertEquals(expected, result.trim(), "Catalog support for DOM");
+ Assert.assertEquals(result.trim(), expected);
}
/*
@@ -327,7 +327,7 @@ public class CatalogSupportBase {
XMLStreamReader streamReader = getStreamReader(
setUseCatalog, useCatalog, catalog, xml, resolver);
String text = getText(streamReader, XMLStreamConstants.CHARACTERS);
- assertEquals(expected, text.trim(), "Catalog support for StAX");
+ Assert.assertEquals(text.trim(), expected);
}
/*
@@ -340,7 +340,7 @@ public class CatalogSupportBase {
XMLStreamReader streamReader = getStreamReader(
setUseCatalog, useCatalog, catalog, xml, resolver);
String text = getText(streamReader, XMLStreamConstants.ENTITY_REFERENCE);
- assertEquals(expected, text.trim(), "Catalog support for StAX");
+ Assert.assertEquals(text.trim(), expected);
}
/*
@@ -601,9 +601,11 @@ public class CatalogSupportBase {
}
/**
- * Returns the text of the first element found by the reader.
+ * Returns the accumulated text of an event type.
+ *
* @param streamReader the XMLStreamReader
- * @return the text of the first element
+ * @param type the type of event requested
+ * @return the text of the accumulated text for the request type
* @throws XMLStreamException
*/
String getText(XMLStreamReader streamReader, int type) throws XMLStreamException {
@@ -662,24 +664,6 @@ public class CatalogSupportBase {
return factory;
}
- void assertNotNull(Object obj, String msg) {
- if (obj == null) {
- debugPrint("Test failed: " + msg);
- } else {
- debugPrint("Test passed: " + obj + " is not null");
- }
- }
-
- void assertEquals(String expected, String actual, String msg) {
- if (!expected.equals(actual)) {
- debugPrint("Test failed: " + msg);
- } else {
- debugPrint("Test passed: ");
- }
- debugPrint("Expected: " + expected);
- debugPrint("Actual: " + actual);
- }
-
void fail(String msg) {
System.out.println("Test failed:");
System.out.println(msg);
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_simple4Catalog.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_simple4Catalog.xml
index af26081369d..dc199c5fad2 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_simple4Catalog.xml
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_simple4Catalog.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_test2Catalog.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_test2Catalog.xml
new file mode 100644
index 00000000000..62c4ed3d105
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/XI_test2Catalog.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
From 8d4f1ae8dffb2556ceb900c81cc78415f88efb60 Mon Sep 17 00:00:00 2001
From: Valerie Peng
Date: Fri, 23 Sep 2016 01:08:24 +0000
Subject: [PATCH 073/114] 8136355: CKM_SSL3_KEY_AND_MAC_DERIVE no longer
available by default on Solaris 12
Enhanced to detect and throw InvalidAlgorithmParameterException if SSLv3 is requested but unsupported
Reviewed-by: xuelei
---
.../pkcs11/P11TlsKeyMaterialGenerator.java | 35 +++++++----
.../pkcs11/P11TlsMasterSecretGenerator.java | 63 +++++++++++--------
.../P11TlsRsaPremasterSecretGenerator.java | 25 +++++++-
.../security/pkcs11/tls/TestKeyMaterial.java | 38 ++++++-----
.../security/pkcs11/tls/TestMasterSecret.java | 30 ++++++---
.../security/pkcs11/tls/TestPremaster.java | 17 ++++-
6 files changed, 138 insertions(+), 70 deletions(-)
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
index c054f312c55..83ecaa1701f 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -68,8 +68,8 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
// master secret as a P11Key
private P11Key p11Key;
- // version, e.g. 0x0301
- private int version;
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
@@ -77,6 +77,11 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java,
+ // if CKM_SSL3_KEY_AND_MAC_DERIVE is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ this.supportSSLv3 = (mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE);
}
protected void engineInit(SecureRandom random) {
@@ -89,20 +94,26 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
if (params instanceof TlsKeyMaterialParameterSpec == false) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsKeyMaterialParameterSpec)params;
+
+ TlsKeyMaterialParameterSpec spec = (TlsKeyMaterialParameterSpec)params;
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
try {
p11Key = P11SecretKeyFactory.convertKey
(token, spec.getMasterSecret(), "TlsMasterSecret");
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException("init() failed", e);
}
- version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
- if ((version < 0x0300) && (version > 0x0302)) {
- throw new InvalidAlgorithmParameterException
- ("Only SSL 3.0, TLS 1.0, and TLS 1.1 are supported");
- }
- // we assume the token supports both the CKM_SSL3_* and the CKM_TLS_*
- // mechanisms
+ this.spec = spec;
+ this.mechanism = (version == 0x0300)?
+ CKM_SSL3_KEY_AND_MAC_DERIVE : CKM_TLS_KEY_AND_MAC_DERIVE;
}
protected void engineInit(int keysize, SecureRandom random) {
@@ -115,8 +126,6 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
throw new IllegalStateException
("TlsKeyMaterialGenerator must be initialized");
}
- mechanism = (version == 0x0300) ? CKM_SSL3_KEY_AND_MAC_DERIVE
- : CKM_TLS_KEY_AND_MAC_DERIVE;
int macBits = spec.getMacKeyLength() << 3;
int ivBits = spec.getIvLength() << 3;
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
index 73a2ac2e890..128952e8a49 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,10 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
private TlsMasterSecretParameterSpec spec;
private P11Key p11Key;
- int version;
+ CK_VERSION ckVersion;
+
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
P11TlsMasterSecretGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
@@ -69,6 +72,11 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java, if
+ // CKM_SSL3_MASTER_KEY_DERIVE is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ supportSSLv3 = (mechanism == CKM_SSL3_MASTER_KEY_DERIVE);
}
protected void engineInit(SecureRandom random) {
@@ -81,7 +89,17 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
if (params instanceof TlsMasterSecretParameterSpec == false) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsMasterSecretParameterSpec)params;
+
+ TlsMasterSecretParameterSpec spec = (TlsMasterSecretParameterSpec)params;
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
+
SecretKey key = spec.getPremasterSecret();
// algorithm should be either TlsRsaPremasterSecret or TlsPremasterSecret,
// but we omit the check
@@ -90,25 +108,7 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException("init() failed", e);
}
- version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
- if ((version < 0x0300) || (version > 0x0302)) {
- throw new InvalidAlgorithmParameterException
- ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported");
- }
- // We assume the token supports the required mechanism. If it does not,
- // generateKey() will fail and the failover should take care of us.
- }
-
- protected void engineInit(int keysize, SecureRandom random) {
- throw new InvalidParameterException(MSG);
- }
-
- protected SecretKey engineGenerateKey() {
- if (spec == null) {
- throw new IllegalStateException
- ("TlsMasterSecretGenerator must be initialized");
- }
- CK_VERSION ckVersion;
+ this.spec = spec;
if (p11Key.getAlgorithm().equals("TlsRsaPremasterSecret")) {
mechanism = (version == 0x0300) ? CKM_SSL3_MASTER_KEY_DERIVE
: CKM_TLS_MASTER_KEY_DERIVE;
@@ -124,6 +124,17 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
: CKM_TLS_MASTER_KEY_DERIVE_DH;
ckVersion = null;
}
+ }
+
+ protected void engineInit(int keysize, SecureRandom random) {
+ throw new InvalidParameterException(MSG);
+ }
+
+ protected SecretKey engineGenerateKey() {
+ if (spec == null) {
+ throw new IllegalStateException
+ ("TlsMasterSecretGenerator must be initialized");
+ }
byte[] clientRandom = spec.getClientRandom();
byte[] serverRandom = spec.getServerRandom();
CK_SSL3_RANDOM_DATA random =
@@ -139,13 +150,12 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
long keyID = token.p11.C_DeriveKey(session.id(),
new CK_MECHANISM(mechanism, params), p11Key.keyID, attributes);
int major, minor;
- ckVersion = params.pVersion;
- if (ckVersion == null) {
+ if (params.pVersion == null) {
major = -1;
minor = -1;
} else {
- major = ckVersion.major;
- minor = ckVersion.minor;
+ major = params.pVersion.major;
+ minor = params.pVersion.minor;
}
SecretKey key = P11Key.masterSecretKey(session, keyID,
"TlsMasterSecret", 48 << 3, attributes, major, minor);
@@ -156,5 +166,4 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
token.releaseSession(session);
}
}
-
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
index 40d3a634ce5..245c067b3d4 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -60,12 +60,20 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
@SuppressWarnings("deprecation")
private TlsRsaPremasterSecretParameterSpec spec;
+ // whether SSLv3 is supported
+ private final boolean supportSSLv3;
+
P11TlsRsaPremasterSecretGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
super();
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
+
+ // Given the current lookup order specified in SunPKCS11.java,
+ // if CKM_SSL3_PRE_MASTER_KEY_GEN is not used to construct this object,
+ // it means that this mech is disabled or unsupported.
+ this.supportSSLv3 = (mechanism == CKM_SSL3_PRE_MASTER_KEY_GEN);
}
protected void engineInit(SecureRandom random) {
@@ -78,7 +86,20 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG);
}
- this.spec = (TlsRsaPremasterSecretParameterSpec)params;
+
+ TlsRsaPremasterSecretParameterSpec spec =
+ (TlsRsaPremasterSecretParameterSpec) params;
+
+ int version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
+
+ if ((version == 0x0300 && !supportSSLv3) || (version < 0x0300) ||
+ (version > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only" + (supportSSLv3? " SSL 3.0,": "") +
+ " TLS 1.0, and TLS 1.1 are supported (0x" +
+ Integer.toHexString(version) + ")");
+ }
+ this.spec = spec;
}
protected void engineInit(int keysize, SecureRandom random) {
diff --git a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java
index 27944e92f89..81a8b4571ba 100644
--- a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java
+++ b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6316539
+ * @bug 6316539 8136355
* @summary Known-answer-test for TlsKeyMaterial generator
* @author Andreas Sterbenz
* @library ..
@@ -37,6 +37,7 @@ import java.io.BufferedReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Provider;
+import java.security.InvalidAlgorithmParameterException;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
@@ -139,21 +140,28 @@ public class TestKeyMaterial extends PKCS11Test {
keyLength, expandedKeyLength, ivLength, macLength,
null, -1, -1);
- kg.init(spec);
- TlsKeyMaterialSpec result =
- (TlsKeyMaterialSpec)kg.generateKey();
- match(lineNumber, clientCipherBytes,
- result.getClientCipherKey(), cipherAlgorithm);
- match(lineNumber, serverCipherBytes,
- result.getServerCipherKey(), cipherAlgorithm);
- match(lineNumber, clientIv, result.getClientIv(), "");
- match(lineNumber, serverIv, result.getServerIv(), "");
- match(lineNumber, clientMacBytes, result.getClientMacKey(), "");
- match(lineNumber, serverMacBytes, result.getServerMacKey(), "");
-
- } else {
+ try {
+ kg.init(spec);
+ TlsKeyMaterialSpec result =
+ (TlsKeyMaterialSpec)kg.generateKey();
+ match(lineNumber, clientCipherBytes,
+ result.getClientCipherKey(), cipherAlgorithm);
+ match(lineNumber, serverCipherBytes,
+ result.getServerCipherKey(), cipherAlgorithm);
+ match(lineNumber, clientIv, result.getClientIv(), "");
+ match(lineNumber, serverIv, result.getServerIv(), "");
+ match(lineNumber, clientMacBytes, result.getClientMacKey(), "");
+ match(lineNumber, serverMacBytes, result.getServerMacKey(), "");
+ } catch (InvalidAlgorithmParameterException iape) {
+ // SSLv3 support is removed in S12
+ if (major == 3 && minor == 0) {
+ System.out.println("Skip testing SSLv3");
+ continue;
+ }
+ }
+ } else {
throw new Exception("Unknown line: " + line);
- }
+ }
}
if (n == 0) {
throw new Exception("no tests");
diff --git a/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java b/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java
index 67ee6e708bd..de6863608d5 100644
--- a/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java
+++ b/jdk/test/sun/security/pkcs11/tls/TestMasterSecret.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6316539
+ * @bug 6316539 8136355
* @summary Known-answer-test for TlsMasterSecret generator
* @author Andreas Sterbenz
* @library ..
@@ -38,6 +38,7 @@ import java.io.BufferedReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Provider;
+import java.security.InvalidAlgorithmParameterException;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
@@ -116,15 +117,24 @@ public class TestMasterSecret extends PKCS11Test {
new TlsMasterSecretParameterSpec(premasterKey,
protoMajor, protoMinor, clientRandom, serverRandom,
null, -1, -1);
- kg.init(spec);
- TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
- byte[] enc = key.getEncoded();
- if (Arrays.equals(master, enc) == false) {
- throw new Exception("mismatch line: " + lineNumber);
- }
- if ((preMajor != key.getMajorVersion()) ||
- (preMinor != key.getMinorVersion())) {
- throw new Exception("version mismatch line: " + lineNumber);
+
+ try {
+ kg.init(spec);
+ TlsMasterSecret key = (TlsMasterSecret)kg.generateKey();
+ byte[] enc = key.getEncoded();
+ if (Arrays.equals(master, enc) == false) {
+ throw new Exception("mismatch line: " + lineNumber);
+ }
+ if ((preMajor != key.getMajorVersion()) ||
+ (preMinor != key.getMinorVersion())) {
+ throw new Exception("version mismatch line: " + lineNumber);
+ }
+ } catch (InvalidAlgorithmParameterException iape) {
+ // SSLv3 support is removed in S12
+ if (preMajor == 3 && preMinor == 0) {
+ System.out.println("Skip testing SSLv3");
+ continue;
+ }
}
} else {
throw new Exception("Unknown line: " + line);
diff --git a/jdk/test/sun/security/pkcs11/tls/TestPremaster.java b/jdk/test/sun/security/pkcs11/tls/TestPremaster.java
index a179bb81c2a..67191a7df28 100644
--- a/jdk/test/sun/security/pkcs11/tls/TestPremaster.java
+++ b/jdk/test/sun/security/pkcs11/tls/TestPremaster.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6316539
+ * @bug 6316539 8136355
* @summary Basic tests for TlsRsaPremasterSecret generator
* @author Andreas Sterbenz
* @library ..
@@ -34,6 +34,7 @@
*/
import java.security.Provider;
+import java.security.InvalidAlgorithmParameterException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
@@ -61,7 +62,7 @@ public class TestPremaster extends PKCS11Test {
System.out.println("OK: " + e);
}
- int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400};
+ int[] protocolVersions = {0x0300, 0x0301, 0x0302};
for (int clientVersion : protocolVersions) {
for (int serverVersion : protocolVersions) {
test(kg, clientVersion, serverVersion);
@@ -81,8 +82,18 @@ public class TestPremaster extends PKCS11Test {
"Testing RSA pre-master secret key generation between " +
"client (0x%04X) and server(0x%04X)%n",
clientVersion, serverVersion);
- kg.init(new TlsRsaPremasterSecretParameterSpec(
+ try {
+ kg.init(new TlsRsaPremasterSecretParameterSpec(
clientVersion, serverVersion));
+ } catch (InvalidAlgorithmParameterException iape) {
+ // S12 removed support for SSL v3.0
+ if (clientVersion == 0x300 || serverVersion == 0x300) {
+ System.out.println("Skip testing SSLv3 due to no support");
+ return;
+ }
+ // unexpected, pass it up
+ throw iape;
+ }
SecretKey key = kg.generateKey();
byte[] encoded = key.getEncoded();
if (encoded != null) { // raw key material may be not extractable
From 8469097dde95e44e6d5c68d6380a836b778a362c Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Fri, 23 Sep 2016 03:15:00 -0700
Subject: [PATCH 074/114] 8085049: java/net/MulticastSocket/TimeToLive.java
fails intermittently with "Address already in use"
Reviewed-by: chegar
---
jdk/test/java/net/MulticastSocket/TimeToLive.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/jdk/test/java/net/MulticastSocket/TimeToLive.java b/jdk/test/java/net/MulticastSocket/TimeToLive.java
index 6d3158f7396..99f2641d5d8 100644
--- a/jdk/test/java/net/MulticastSocket/TimeToLive.java
+++ b/jdk/test/java/net/MulticastSocket/TimeToLive.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@ public class TimeToLive {
static int[] bad_ttls = { -1, 256 };
public static void main(String[] args) throws Exception {
- MulticastSocket socket = new MulticastSocket(6789);
+ MulticastSocket socket = new MulticastSocket();
int ttl = socket.getTimeToLive();
System.out.println("default ttl: " + ttl);
for (int i = 0; i < new_ttls.length; i++) {
From 281862a6aa0e34d98193960b3d30937e304d2eef Mon Sep 17 00:00:00 2001
From: Michael Haupt
Date: Fri, 23 Sep 2016 15:20:49 +0200
Subject: [PATCH 075/114] 8161211: better inlining support for loop bytecode
intrinsics
Reviewed-by: jrose, vlivanov, redestad
---
.../java/lang/invoke/BoundMethodHandle.java | 1 -
.../lang/invoke/InvokerBytecodeGenerator.java | 99 ++++++++++------
.../classes/java/lang/invoke/LambdaForm.java | 5 +-
.../java/lang/invoke/MethodHandleImpl.java | 110 +++++++++++-------
.../java/lang/invoke/MethodHandles.java | 16 ++-
.../java/lang/invoke/MethodHandlesTest.java | 7 ++
6 files changed, 150 insertions(+), 88 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
index 461dd3967cb..395e80ca6b0 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -869,5 +869,4 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
static SpeciesData speciesData_LLL() { return checkCache(3, "LLL"); }
static SpeciesData speciesData_LLLL() { return checkCache(4, "LLLL"); }
static SpeciesData speciesData_LLLLL() { return checkCache(5, "LLLLL"); }
- static SpeciesData speciesData_LLLLLL() { return checkCache(6, "LLLLLL"); }
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index afb04b6efa4..ea6236aa2d9 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -39,14 +39,14 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
-import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.BasicType;
import static java.lang.invoke.LambdaForm.BasicType.*;
-import static java.lang.invoke.LambdaForm.Kind.*;
+import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
@@ -65,6 +65,9 @@ class InvokerBytecodeGenerator {
private static final String OBJ = "java/lang/Object";
private static final String OBJARY = "[Ljava/lang/Object;";
+ private static final String LOOP_CLAUSES = MHI + "$LoopClauses";
+ private static final String MHARY2 = "[[L" + MH + ";";
+
private static final String LF_SIG = "L" + LF + ";";
private static final String LFN_SIG = "L" + LFN + ";";
private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
@@ -1319,38 +1322,43 @@ class InvokerBytecodeGenerator {
* The pattern looks like (Cf. MethodHandleImpl.loop):
* {@code
* // a0: BMH
- * // a1: inits, a2: steps, a3: preds, a4: finis
- * // a5: box, a6: unbox
- * // a7 (and following): arguments
- * loop=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{
- * t8:L=MethodHandle.invokeBasic(a5:L,a7:L); // box the arguments into an Object[]
- * t9:L=MethodHandleImpl.loop(bt:L,a1:L,a2:L,a3:L,a4:L,t8:L); // call the loop executor (with supplied types in bt)
- * t10:L=MethodHandle.invokeBasic(a6:L,t9:L);t10:L} // unbox the result; return the result
+ * // a1: LoopClauses (containing an array of arrays: inits, steps, preds, finis)
+ * // a2: box, a3: unbox
+ * // a4 (and following): arguments
+ * loop=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L)=>{
+ * t5:L=MethodHandle.invokeBasic(a2:L,a4:L); // box the arguments into an Object[]
+ * t6:L=MethodHandleImpl.loop(bt:L,a1:L,t5:L); // call the loop executor (with supplied types in bt)
+ * t7:L=MethodHandle.invokeBasic(a3:L,t6:L);t7:L} // unbox the result; return the result
* }
*
* It is compiled into bytecode equivalent to the code seen in {@link MethodHandleImpl#loop(BasicType[],
- * MethodHandle[], MethodHandle[], MethodHandle[], MethodHandle[], Object...)}, with the difference that no arrays
+ * MethodHandleImpl.LoopClauses, Object...)}, with the difference that no arrays
* will be used for local state storage. Instead, the local state will be mapped to actual stack slots.
*
* Bytecode generation applies an unrolling scheme to enable better bytecode generation regarding local state type
* handling. The generated bytecode will have the following form ({@code void} types are ignored for convenience).
* Assume there are {@code C} clauses in the loop.
*
{@code
- * INIT: (INIT_SEQ for clause 1)
- * ...
- * (INIT_SEQ for clause C)
- * LOOP: (LOOP_SEQ for clause 1)
- * ...
- * (LOOP_SEQ for clause C)
- * GOTO LOOP
- * DONE: ...
+ * PREINIT: ALOAD_1
+ * CHECKCAST LoopClauses
+ * GETFIELD LoopClauses.clauses
+ * ASTORE clauseDataIndex // place the clauses 2-dimensional array on the stack
+ * INIT: (INIT_SEQ for clause 1)
+ * ...
+ * (INIT_SEQ for clause C)
+ * LOOP: (LOOP_SEQ for clause 1)
+ * ...
+ * (LOOP_SEQ for clause C)
+ * GOTO LOOP
+ * DONE: ...
* }
*
* The {@code INIT_SEQ_x} sequence for clause {@code x} (with {@code x} ranging from {@code 0} to {@code C-1}) has
* the following shape. Assume slot {@code vx} is used to hold the state for clause {@code x}.
*
{@code
- * INIT_SEQ_x: ALOAD inits
- * CHECKCAST MethodHandle[]
+ * INIT_SEQ_x: ALOAD clauseDataIndex
+ * ICONST_0
+ * AALOAD // load the inits array
* ICONST x
* AALOAD // load the init handle for clause x
* load args
@@ -1361,24 +1369,27 @@ class InvokerBytecodeGenerator {
* The {@code LOOP_SEQ_x} sequence for clause {@code x} (with {@code x} ranging from {@code 0} to {@code C-1}) has
* the following shape. Again, assume slot {@code vx} is used to hold the state for clause {@code x}.
* {@code
- * LOOP_SEQ_x: ALOAD steps
- * CHECKCAST MethodHandle[]
+ * LOOP_SEQ_x: ALOAD clauseDataIndex
+ * ICONST_1
+ * AALOAD // load the steps array
* ICONST x
* AALOAD // load the step handle for clause x
* load locals
* load args
* INVOKEVIRTUAL MethodHandle.invokeBasic
* store vx
- * ALOAD preds
- * CHECKCAST MethodHandle[]
+ * ALOAD clauseDataIndex
+ * ICONST_2
+ * AALOAD // load the preds array
* ICONST x
* AALOAD // load the pred handle for clause x
* load locals
* load args
* INVOKEVIRTUAL MethodHandle.invokeBasic
* IFNE LOOP_SEQ_x+1 // predicate returned false -> jump to next clause
- * ALOAD finis
- * CHECKCAST MethodHandle[]
+ * ALOAD clauseDataIndex
+ * ICONST_3
+ * AALOAD // load the finis array
* ICONST x
* AALOAD // load the fini handle for clause x
* load locals
@@ -1397,8 +1408,12 @@ class InvokerBytecodeGenerator {
BasicType[] loopClauseTypes = (BasicType[]) invoker.arguments[0];
Class>[] loopLocalStateTypes = Stream.of(loopClauseTypes).
filter(bt -> bt != BasicType.V_TYPE).map(BasicType::basicTypeClass).toArray(Class>[]::new);
+ Class>[] localTypes = new Class>[loopLocalStateTypes.length + 1];
+ localTypes[0] = MethodHandleImpl.LoopClauses.class;
+ System.arraycopy(loopLocalStateTypes, 0, localTypes, 1, loopLocalStateTypes.length);
- final int firstLoopStateIndex = extendLocalsMap(loopLocalStateTypes);
+ final int clauseDataIndex = extendLocalsMap(localTypes);
+ final int firstLoopStateIndex = clauseDataIndex + 1;
Class> returnType = result.function.resolvedHandle().type().returnType();
MethodType loopType = args.function.resolvedHandle().type()
@@ -1420,10 +1435,16 @@ class InvokerBytecodeGenerator {
Label lDone = new Label();
Label lNext;
+ // PREINIT:
+ emitPushArgument(MethodHandleImpl.LoopClauses.class, invoker.arguments[1]);
+ mv.visitFieldInsn(Opcodes.GETFIELD, LOOP_CLAUSES, "clauses", MHARY2);
+ emitAstoreInsn(clauseDataIndex);
+
// INIT:
for (int c = 0, state = 0; c < nClauses; ++c) {
MethodType cInitType = loopType.changeReturnType(loopClauseTypes[c].basicTypeClass());
- emitLoopHandleInvoke(invoker, inits, c, args, false, cInitType, loopLocalStateTypes, firstLoopStateIndex);
+ emitLoopHandleInvoke(invoker, inits, c, args, false, cInitType, loopLocalStateTypes, clauseDataIndex,
+ firstLoopStateIndex);
if (cInitType.returnType() != void.class) {
emitStoreInsn(BasicType.basicType(cInitType.returnType()), firstLoopStateIndex + state);
++state;
@@ -1440,18 +1461,21 @@ class InvokerBytecodeGenerator {
boolean isVoid = stepType.returnType() == void.class;
// invoke loop step
- emitLoopHandleInvoke(invoker, steps, c, args, true, stepType, loopLocalStateTypes, firstLoopStateIndex);
+ emitLoopHandleInvoke(invoker, steps, c, args, true, stepType, loopLocalStateTypes, clauseDataIndex,
+ firstLoopStateIndex);
if (!isVoid) {
emitStoreInsn(BasicType.basicType(stepType.returnType()), firstLoopStateIndex + state);
++state;
}
// invoke loop predicate
- emitLoopHandleInvoke(invoker, preds, c, args, true, predType, loopLocalStateTypes, firstLoopStateIndex);
+ emitLoopHandleInvoke(invoker, preds, c, args, true, predType, loopLocalStateTypes, clauseDataIndex,
+ firstLoopStateIndex);
mv.visitJumpInsn(Opcodes.IFNE, lNext);
// invoke fini
- emitLoopHandleInvoke(invoker, finis, c, args, true, finiType, loopLocalStateTypes, firstLoopStateIndex);
+ emitLoopHandleInvoke(invoker, finis, c, args, true, finiType, loopLocalStateTypes, clauseDataIndex,
+ firstLoopStateIndex);
mv.visitJumpInsn(Opcodes.GOTO, lDone);
// this is the beginning of the next loop clause
@@ -1483,9 +1507,10 @@ class InvokerBytecodeGenerator {
}
private void emitLoopHandleInvoke(Name holder, int handles, int clause, Name args, boolean pushLocalState,
- MethodType type, Class>[] loopLocalStateTypes, int firstLoopStateSlot) {
+ MethodType type, Class>[] loopLocalStateTypes, int clauseDataSlot,
+ int firstLoopStateSlot) {
// load handle for clause
- emitPushArgument(holder, handles);
+ emitPushClauseArray(clauseDataSlot, handles);
emitIconstInsn(clause);
mv.visitInsn(Opcodes.AALOAD);
// load loop state (preceding the other arguments)
@@ -1499,6 +1524,12 @@ class InvokerBytecodeGenerator {
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.toMethodDescriptorString(), false);
}
+ private void emitPushClauseArray(int clauseDataSlot, int which) {
+ emitAloadInsn(clauseDataSlot);
+ emitIconstInsn(which - 1);
+ mv.visitInsn(Opcodes.AALOAD);
+ }
+
private void emitZero(BasicType type) {
switch (type) {
case I_TYPE: mv.visitInsn(Opcodes.ICONST_0); break;
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
index 6fdf21e2c91..bcc825bcf15 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
@@ -41,7 +41,6 @@ import java.util.HashMap;
import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
import static java.lang.invoke.MethodHandleStatics.*;
-import java.util.Objects;
/**
* The symbolic, non-executable form of a method handle's invocation semantics.
@@ -732,9 +731,9 @@ class LambdaForm {
boolean isLoop(int pos) {
// loop idiom:
// t_{n}:L=MethodHandle.invokeBasic(...)
- // t_{n+1}:L=MethodHandleImpl.loop(types, *, *, *, *, t_{n})
+ // t_{n+1}:L=MethodHandleImpl.loop(types, *, t_{n})
// t_{n+2}:?=MethodHandle.invokeBasic(*, t_{n+1})
- return isMatchingIdiom(pos, "loop", 5);
+ return isMatchingIdiom(pos, "loop", 2);
}
/*
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index 4fe4bb524a7..ca4f050553f 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -1689,8 +1689,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
NF_tryFinally = new NamedFunction(MethodHandleImpl.class
.getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
NF_loop = new NamedFunction(MethodHandleImpl.class
- .getDeclaredMethod("loop", BasicType[].class, MethodHandle[].class, MethodHandle[].class,
- MethodHandle[].class, MethodHandle[].class, Object[].class));
+ .getDeclaredMethod("loop", BasicType[].class, LoopClauses.class, Object[].class));
NF_throwException = new NamedFunction(MethodHandleImpl.class
.getDeclaredMethod("throwException", Throwable.class));
NF_profileBoolean = new NamedFunction(MethodHandleImpl.class
@@ -1794,12 +1793,13 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
MethodHandle unboxResult = unboxResultHandle(tloop);
- BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLLL();
+ LoopClauses clauseData =
+ new LoopClauses(new MethodHandle[][]{toArray(init), toArray(step), toArray(pred), toArray(fini)});
+ BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
BoundMethodHandle mh;
try {
- mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) toArray(init),
- (Object) toArray(step), (Object) toArray(pred), (Object) toArray(fini), (Object) collectArgs,
- (Object) unboxResult);
+ mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) clauseData,
+ (Object) collectArgs, (Object) unboxResult);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -1818,23 +1818,20 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* {@code t12}):
* {@code
* loop=Lambda(a0:L,a1:L)=>{
- * t2:L=BoundMethodHandle$Species_L6.argL0(a0:L); // array of init method handles
- * t3:L=BoundMethodHandle$Species_L6.argL1(a0:L); // array of step method handles
- * t4:L=BoundMethodHandle$Species_L6.argL2(a0:L); // array of pred method handles
- * t5:L=BoundMethodHandle$Species_L6.argL3(a0:L); // array of fini method handles
- * t6:L=BoundMethodHandle$Species_L6.argL4(a0:L); // helper handle to box the arguments into an Object[]
- * t7:L=BoundMethodHandle$Species_L6.argL5(a0:L); // helper handle to unbox the result
- * t8:L=MethodHandle.invokeBasic(t6:L,a1:L); // box the arguments into an Object[]
- * t9:L=MethodHandleImpl.loop(null,t2:L,t3:L,t4:L,t5:L,t6:L); // call the loop executor
- * t10:L=MethodHandle.invokeBasic(t7:L,t9:L);t10:L} // unbox the result; return the result
+ * t2:L=BoundMethodHandle$Species_L3.argL0(a0:L); // LoopClauses holding init, step, pred, fini handles
+ * t3:L=BoundMethodHandle$Species_L3.argL1(a0:L); // helper handle to box the arguments into an Object[]
+ * t4:L=BoundMethodHandle$Species_L3.argL2(a0:L); // helper handle to unbox the result
+ * t5:L=MethodHandle.invokeBasic(t3:L,a1:L); // box the arguments into an Object[]
+ * t6:L=MethodHandleImpl.loop(null,t2:L,t3:L); // call the loop executor
+ * t7:L=MethodHandle.invokeBasic(t4:L,t6:L);t7:L} // unbox the result; return the result
* }
*
- * {@code argL0} through {@code argL3} are the arrays of init, step, pred, and fini method handles.
- * {@code argL4} and {@code argL5} are auxiliary method handles: {@code argL2} boxes arguments and wraps them into
- * {@code Object[]} ({@code ValueConversions.array()}), and {@code argL3} unboxes the result if necessary
+ * {@code argL0} is a LoopClauses instance holding, in a 2-dimensional array, the init, step, pred, and fini method
+ * handles. {@code argL1} and {@code argL2} are auxiliary method handles: {@code argL1} boxes arguments and wraps
+ * them into {@code Object[]} ({@code ValueConversions.array()}), and {@code argL2} unboxes the result if necessary
* ({@code ValueConversions.unbox()}).
*
- * Having {@code t6} and {@code t7} passed in via a BMH and not hardcoded in the lambda form allows to share lambda
+ * Having {@code t3} and {@code t4} passed in via a BMH and not hardcoded in the lambda form allows to share lambda
* forms among loop combinators with the same basic type.
*
* The above template is instantiated by using the {@link LambdaFormEditor} to replace the {@code null} argument to
@@ -1845,15 +1842,12 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
private static LambdaForm makeLoopForm(MethodType basicType, BasicType[] localVarTypes) {
MethodType lambdaType = basicType.invokerType();
- final int THIS_MH = 0; // the BMH_LLLLLL
+ final int THIS_MH = 0; // the BMH_LLL
final int ARG_BASE = 1; // start of incoming arguments
final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
int nameCursor = ARG_LIMIT;
- final int GET_INITS = nameCursor++;
- final int GET_STEPS = nameCursor++;
- final int GET_PREDS = nameCursor++;
- final int GET_FINIS = nameCursor++;
+ final int GET_CLAUSE_DATA = nameCursor++;
final int GET_COLLECT_ARGS = nameCursor++;
final int GET_UNBOX_RESULT = nameCursor++;
final int BOXED_ARGS = nameCursor++;
@@ -1864,14 +1858,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
if (lform == null) {
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
- BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLLL();
+ BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
names[THIS_MH] = names[THIS_MH].withConstraint(data);
- names[GET_INITS] = new Name(data.getterFunction(0), names[THIS_MH]);
- names[GET_STEPS] = new Name(data.getterFunction(1), names[THIS_MH]);
- names[GET_PREDS] = new Name(data.getterFunction(2), names[THIS_MH]);
- names[GET_FINIS] = new Name(data.getterFunction(3), names[THIS_MH]);
- names[GET_COLLECT_ARGS] = new Name(data.getterFunction(4), names[THIS_MH]);
- names[GET_UNBOX_RESULT] = new Name(data.getterFunction(5), names[THIS_MH]);
+ names[GET_CLAUSE_DATA] = new Name(data.getterFunction(0), names[THIS_MH]);
+ names[GET_COLLECT_ARGS] = new Name(data.getterFunction(1), names[THIS_MH]);
+ names[GET_UNBOX_RESULT] = new Name(data.getterFunction(2), names[THIS_MH]);
// t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
MethodType collectArgsType = basicType.changeReturnType(Object.class);
@@ -1881,10 +1872,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT - ARG_BASE);
names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.LOOP), args);
- // t_{i+1}:L=MethodHandleImpl.loop(localTypes:L,inits:L,steps:L,preds:L,finis:L,t_{i}:L);
+ // t_{i+1}:L=MethodHandleImpl.loop(localTypes:L,clauses:L,t_{i}:L);
Object[] lArgs =
new Object[]{null, // placeholder for BasicType[] localTypes - will be added by LambdaFormEditor
- names[GET_INITS], names[GET_STEPS], names[GET_PREDS], names[GET_FINIS], names[BOXED_ARGS]};
+ names[GET_CLAUSE_DATA], names[BOXED_ARGS]};
names[LOOP] = new Name(NF_loop, lArgs);
// t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
@@ -1900,22 +1891,52 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
return lform.editor().noteLoopLocalTypesForm(BOXED_ARGS, localVarTypes);
}
+ static class LoopClauses {
+ @Stable final MethodHandle[][] clauses;
+ LoopClauses(MethodHandle[][] clauses) {
+ assert clauses.length == 4;
+ this.clauses = clauses;
+ }
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer("LoopClauses -- ");
+ for (int i = 0; i < 4; ++i) {
+ if (i > 0) {
+ sb.append(" ");
+ }
+ sb.append('<').append(i).append(">: ");
+ MethodHandle[] hs = clauses[i];
+ for (int j = 0; j < hs.length; ++j) {
+ if (j > 0) {
+ sb.append(" ");
+ }
+ sb.append('*').append(j).append(": ").append(hs[j]).append('\n');
+ }
+ }
+ sb.append(" --\n");
+ return sb.toString();
+ }
+ }
/**
* Intrinsified during LambdaForm compilation
* (see {@link InvokerBytecodeGenerator#emitLoop(int)}).
*/
@LambdaForm.Hidden
- static Object loop(BasicType[] localTypes, MethodHandle[] init, MethodHandle[] step, MethodHandle[] pred,
- MethodHandle[] fini, Object... av) throws Throwable {
+ static Object loop(BasicType[] localTypes, LoopClauses clauseData, Object... av) throws Throwable {
+ final MethodHandle[] init = clauseData.clauses[0];
+ final MethodHandle[] step = clauseData.clauses[1];
+ final MethodHandle[] pred = clauseData.clauses[2];
+ final MethodHandle[] fini = clauseData.clauses[3];
int varSize = (int) Stream.of(init).filter(h -> h.type().returnType() != void.class).count();
int nArgs = init[0].type().parameterCount();
Object[] varsAndArgs = new Object[varSize + nArgs];
for (int i = 0, v = 0; i < init.length; ++i) {
- if (init[i].type().returnType() == void.class) {
- init[i].asFixedArity().invokeWithArguments(av);
+ MethodHandle ih = init[i];
+ if (ih.type().returnType() == void.class) {
+ ih.invokeWithArguments(av);
} else {
- varsAndArgs[v++] = init[i].asFixedArity().invokeWithArguments(av);
+ varsAndArgs[v++] = ih.invokeWithArguments(av);
}
}
System.arraycopy(av, 0, varsAndArgs, varSize, nArgs);
@@ -1926,12 +1947,12 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
MethodHandle s = step[i];
MethodHandle f = fini[i];
if (s.type().returnType() == void.class) {
- s.asFixedArity().invokeWithArguments(varsAndArgs);
+ s.invokeWithArguments(varsAndArgs);
} else {
- varsAndArgs[v++] = s.asFixedArity().invokeWithArguments(varsAndArgs);
+ varsAndArgs[v++] = s.invokeWithArguments(varsAndArgs);
}
- if (!(boolean) p.asFixedArity().invokeWithArguments(varsAndArgs)) {
- return f.asFixedArity().invokeWithArguments(varsAndArgs);
+ if (!(boolean) p.invokeWithArguments(varsAndArgs)) {
+ return f.invokeWithArguments(varsAndArgs);
}
}
}
@@ -2122,14 +2143,13 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
Throwable t = null;
Object r = null;
try {
- // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
- r = target.asFixedArity().invokeWithArguments(av);
+ r = target.invokeWithArguments(av);
} catch (Throwable thrown) {
t = thrown;
throw t;
} finally {
Object[] args = target.type().returnType() == void.class ? prepend(av, t) : prepend(av, t, r);
- r = cleanup.asFixedArity().invokeWithArguments(args);
+ r = cleanup.invokeWithArguments(args);
}
return r;
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 86685b605de..28364e53ae9 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -4368,10 +4368,11 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
}
// Step 4: fill in missing parameter types.
- List finit = fillParameterTypes(init, commonSuffix);
- List fstep = fillParameterTypes(step, commonParameterSequence);
- List fpred = fillParameterTypes(pred, commonParameterSequence);
- List ffini = fillParameterTypes(fini, commonParameterSequence);
+ // Also convert all handles to fixed-arity handles.
+ List finit = fixArities(fillParameterTypes(init, commonSuffix));
+ List fstep = fixArities(fillParameterTypes(step, commonParameterSequence));
+ List fpred = fixArities(fillParameterTypes(pred, commonParameterSequence));
+ List ffini = fixArities(fillParameterTypes(fini, commonParameterSequence));
assert finit.stream().map(MethodHandle::type).map(MethodType::parameterList).
allMatch(pl -> pl.equals(commonSuffix));
@@ -4389,6 +4390,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
}).collect(Collectors.toList());
}
+ private static List fixArities(List hs) {
+ return hs.stream().map(MethodHandle::asFixedArity).collect(Collectors.toList());
+ }
+
/**
* Constructs a {@code while} loop from an initializer, a body, and a predicate. This is a convenience wrapper for
* the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
@@ -4887,7 +4892,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
// target parameter list.
cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0);
- return MethodHandleImpl.makeTryFinally(target, cleanup, rtype, targetParamTypes);
+ // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
+ return MethodHandleImpl.makeTryFinally(target.asFixedArity(), cleanup.asFixedArity(), rtype, targetParamTypes);
}
/**
diff --git a/jdk/test/java/lang/invoke/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java
index 0f4e7236c62..2098b5bb2a8 100644
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java
@@ -632,6 +632,7 @@ public class MethodHandlesTest {
}
public void testFindVirtualClone0() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
// test some ad hoc system methods
testFindVirtual(false, PUBLIC, Object.class, Object.class, "clone");
@@ -2798,11 +2799,17 @@ public class MethodHandlesTest {
toClauseMajor(postClauses, inits, steps, usePreds, finis);
MethodHandle pre = MethodHandles.loop(preClauses);
MethodHandle post = MethodHandles.loop(postClauses);
+ if (verbosity >= 6) {
+ System.out.println("pre-handle: " + pre);
+ }
Object[] preResults = (Object[]) pre.invokeWithArguments(args);
if (verbosity >= 4) {
System.out.println("pre-checked: expected " + Arrays.asList(preCheckedResults[i]) + ", actual " +
Arrays.asList(preResults));
}
+ if (verbosity >= 6) {
+ System.out.println("post-handle: " + post);
+ }
Object[] postResults = (Object[]) post.invokeWithArguments(args);
if (verbosity >= 4) {
System.out.println("post-checked: expected " + Arrays.asList(postCheckedResults[i]) + ", actual " +
From 90dc5934608f07fc04e7caf8cfe899c757743849 Mon Sep 17 00:00:00 2001
From: Rob McKenna
Date: Fri, 23 Sep 2016 15:31:46 +0100
Subject: [PATCH 076/114] 8159410: InetAddress.isReachable returns true for non
existing IP adresses
Reviewed-by: chegar, coffeys
---
.../windows/native/libnet/Inet4AddressImpl.c | 50 +++++++++++++++++--
1 file changed, 47 insertions(+), 3 deletions(-)
diff --git a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
index 30b2a93ffcc..debc50a1543 100644
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
@@ -442,7 +443,15 @@ ping4(JNIEnv *env,
DWORD ReplySize = 0;
jboolean ret = JNI_FALSE;
- ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366051%28v=vs.85%29.aspx
+ ReplySize = sizeof(ICMP_ECHO_REPLY) // The buffer should be large enough
+ // to hold at least one ICMP_ECHO_REPLY
+ // structure
+ + sizeof(SendData) // plus RequestSize bytes of data.
+ + 8; // This buffer should also be large enough
+ // to also hold 8 more bytes of data
+ // (the size of an ICMP error message)
+
ReplyBuffer = (VOID*) malloc(ReplySize);
if (ReplyBuffer == NULL) {
IcmpCloseHandle(hIcmpFile);
@@ -478,10 +487,45 @@ ping4(JNIEnv *env,
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
}
- if (dwRetVal != 0) {
+ if (dwRetVal == 0) { // if the call failed
+ TCHAR *buf;
+ DWORD err = WSAGetLastError();
+ switch (err) {
+ case ERROR_NO_NETWORK:
+ case ERROR_NETWORK_UNREACHABLE:
+ case ERROR_HOST_UNREACHABLE:
+ case ERROR_PROTOCOL_UNREACHABLE:
+ case ERROR_PORT_UNREACHABLE:
+ case ERROR_REQUEST_ABORTED:
+ case ERROR_INCORRECT_ADDRESS:
+ case ERROR_HOST_DOWN:
+ case WSAEHOSTUNREACH: /* Host Unreachable */
+ case WSAENETUNREACH: /* Network Unreachable */
+ case WSAENETDOWN: /* Network is down */
+ case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
+ case IP_REQ_TIMED_OUT:
+ break;
+ default:
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&buf, 0, NULL);
+ NET_ThrowNew(env, err, buf);
+ LocalFree(buf);
+ break;
+ }
+ } else {
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
- if ((int)pEchoReply->RoundTripTime <= timeout)
+
+ // This is to take into account the undocumented minimum
+ // timeout mentioned in the IcmpSendEcho call above.
+ // We perform an extra check to make sure that our
+ // roundtrip time was less than our desired timeout
+ // for cases where that timeout is < 1000ms.
+ if (pEchoReply->Status == IP_SUCCESS
+ && (int)pEchoReply->RoundTripTime <= timeout)
+ {
ret = JNI_TRUE;
+ }
}
free(ReplyBuffer);
From 72a44a46fa380a5eb9ee3ee712608b0933618af6 Mon Sep 17 00:00:00 2001
From: Sergei Kovalev
Date: Fri, 23 Sep 2016 12:08:38 +0300
Subject: [PATCH 077/114] 8166553: undeclared dependencies for two IO tests
Reviewed-by: bpb
---
jdk/test/java/io/PrintStream/FormatLocale.java | 3 ++-
jdk/test/sun/nio/cs/TestUnmappable.java | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/jdk/test/java/io/PrintStream/FormatLocale.java b/jdk/test/java/io/PrintStream/FormatLocale.java
index 08d6817d193..ce10a21b388 100644
--- a/jdk/test/java/io/PrintStream/FormatLocale.java
+++ b/jdk/test/java/io/PrintStream/FormatLocale.java
@@ -21,10 +21,11 @@
* questions.
*/
-/**
+/*
* @test
* @bug 8146156
* @summary test whether conversion follows Locale.Category.FORMAT locale.
+ * @modules jdk.localedata
* @run main/othervm FormatLocale
*/
diff --git a/jdk/test/sun/nio/cs/TestUnmappable.java b/jdk/test/sun/nio/cs/TestUnmappable.java
index 6273807cce3..8204fdf4d10 100644
--- a/jdk/test/sun/nio/cs/TestUnmappable.java
+++ b/jdk/test/sun/nio/cs/TestUnmappable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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,11 +28,11 @@
* @bug 8008386
* @summary (cs) Unmappable leading should be decoded to replacement.
* Tests for Shift_JIS and MS932 decoding
+ * @modules jdk.charsets
* @run main TestUnmappable
*/
-import java.nio.*;
-import java.nio.charset.*;
+import java.nio.charset.Charset;
public class TestUnmappable {
public static void main(String args[]) throws Exception {
From 35439dec91a3d12392dcc363fa0573c7f219d5a0 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Fri, 23 Sep 2016 15:35:32 +0200
Subject: [PATCH 078/114] 8047347: com.sun.source.util.Trees breaks the
compiler
Clearing synthetic constructors and super constructor calls between annotation processing rounds.
Reviewed-by: jjg
---
.../com/sun/tools/javac/api/JavacTrees.java | 20 ++---
.../JavacProcessingEnvironment.java | 24 +++++-
.../model/trees/BrokenEnumConstructor.java | 40 +++++++++
.../model/trees/BrokenEnumConstructor.out | 2 +
.../model/trees/OnDemandAttribution.java | 84 +++++++++++++------
.../model/trees/OnDemandAttributionData.java | 59 +++++++++++++
6 files changed, 191 insertions(+), 38 deletions(-)
create mode 100644 langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java
create mode 100644 langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out
create mode 100644 langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
index abd811b1ea6..fd3813600c6 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
@@ -383,18 +383,16 @@ public class JavacTrees extends DocTrees {
JCTree tree = (JCTree) path.getLeaf();
Symbol sym = TreeInfo.symbolFor(tree);
if (sym == null) {
- if (TreeInfo.isDeclaration(tree)) {
- for (TreePath p = path; p != null; p = p.getParentPath()) {
- JCTree t = (JCTree) p.getLeaf();
- if (t.hasTag(JCTree.Tag.CLASSDEF)) {
- JCClassDecl ct = (JCClassDecl) t;
- if (ct.sym != null) {
- if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
- attr.attribClass(ct.pos(), ct.sym);
- sym = TreeInfo.symbolFor(tree);
- }
- break;
+ for (TreePath p = path; p != null; p = p.getParentPath()) {
+ JCTree t = (JCTree) p.getLeaf();
+ if (t.hasTag(JCTree.Tag.CLASSDEF)) {
+ JCClassDecl ct = (JCClassDecl) t;
+ if (ct.sym != null) {
+ if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
+ attr.attribClass(ct.pos(), ct.sym);
+ sym = TreeInfo.symbolFor(tree);
}
+ break;
}
}
}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index ce066f83a39..4e1d4dd42d3 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -1503,13 +1503,35 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
}
public void visitClassDef(JCClassDecl node) {
+ super.visitClassDef(node);
+ // remove generated constructor that may have been added during attribution:
+ List beforeConstructor = List.nil();
+ List defs = node.defs;
+ while (defs.nonEmpty() && !defs.head.hasTag(Tag.METHODDEF)) {
+ beforeConstructor = beforeConstructor.prepend(defs.head);
+ defs = defs.tail;
+ }
+ if (defs.nonEmpty() &&
+ (((JCMethodDecl) defs.head).mods.flags & Flags.GENERATEDCONSTR) != 0) {
+ defs = defs.tail;
+ while (beforeConstructor.nonEmpty()) {
+ defs = defs.prepend(beforeConstructor.head);
+ beforeConstructor = beforeConstructor.tail;
+ }
+ node.defs = defs;
+ }
if (node.sym != null) {
node.sym.completer = new ImplicitCompleter(topLevel);
}
node.sym = null;
- super.visitClassDef(node);
}
public void visitMethodDef(JCMethodDecl node) {
+ // remove super constructor call that may have been added during attribution:
+ if (TreeInfo.isConstructor(node) && node.sym != null && node.sym.owner.isEnum() &&
+ node.body.stats.nonEmpty() && TreeInfo.isSuperCall(node.body.stats.head) &&
+ node.body.stats.head.pos == node.body.pos) {
+ node.body.stats = node.body.stats.tail;
+ }
node.sym = null;
super.visitMethodDef(node);
}
diff --git a/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java
new file mode 100644
index 00000000000..ed39a82d6a9
--- /dev/null
+++ b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 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 8047347
+ * @summary Verify that an explicit (incorrect) super constructor invocation in enums is not cleared
+ * by JavacProcessingEnvironment
+ * @library /tools/javac/lib
+ * @modules jdk.compiler
+ * @build JavacTestingAbstractProcessor OnDemandAttribution
+ * @compile/process/fail/ref=BrokenEnumConstructor.out -XDrawDiagnostics -processor OnDemandAttribution BrokenEnumConstructor.java
+ */
+
+public enum BrokenEnumConstructor {
+
+ A;
+
+ BrokenEnumConstructor() {super(); /*illegal*/}
+}
diff --git a/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out
new file mode 100644
index 00000000000..9b514e7223c
--- /dev/null
+++ b/langtools/test/tools/javac/processing/model/trees/BrokenEnumConstructor.out
@@ -0,0 +1,2 @@
+BrokenEnumConstructor.java:39:30: compiler.err.call.to.super.not.allowed.in.enum.ctor: BrokenEnumConstructor
+1 error
diff --git a/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java b/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java
index ce7c3e655c1..6c7d477bf3c 100644
--- a/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java
+++ b/langtools/test/tools/javac/processing/model/trees/OnDemandAttribution.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,56 +23,88 @@
/*
* @test
- * @bug 8038455
+ * @bug 8038455 8047347
* @summary Verify that in-method ClassSymbols from one round do not affect ClassSymbols in
* following rounds.
* @library /tools/javac/lib
* @modules jdk.compiler
* @build JavacTestingAbstractProcessor OnDemandAttribution
- * @compile/process -processor OnDemandAttribution OnDemandAttribution.java
+ * @clean Gen
+ * @compile/process -processor OnDemandAttribution OnDemandAttributionData.java
*/
+import java.io.IOException;
+import java.io.Writer;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
-import static javax.lang.model.util.ElementFilter.*;
+import static javax.lang.model.util.ElementFilter.constructorsIn;
import com.sun.source.tree.*;
import com.sun.source.util.*;
public class OnDemandAttribution extends JavacTestingAbstractProcessor {
public OnDemandAttribution() {
- class Local { }
- new Object() { };
}
- public boolean process(Set extends TypeElement> annos,RoundEnvironment rEnv) {
- TypeElement currentClass = elements.getTypeElement("OnDemandAttribution");
- ExecutableElement constr = constructorsIn(currentClass.getEnclosedElements()).get(0);
- Trees trees = Trees.instance(processingEnv);
- TreePath path = trees.getPath(constr);
+ int round;
+ Set roots = new HashSet<>();
- new TreePathScanner() {
- @Override public Void visitClass(ClassTree node, Void p) {
- if (node.getSimpleName().contentEquals("Local")) {
- //will also attribute the body on demand:
+ public boolean process(Set extends TypeElement> annos,RoundEnvironment rEnv) {
+ for (Element root : rEnv.getRootElements()) {
+ while (root.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
+ root = root.getEnclosingElement();
+ }
+ roots.add(((TypeElement) root).getQualifiedName().toString());
+ }
+ for (String root : roots) {
+ TypeElement currentClass = elements.getTypeElement(root);
+ ExecutableElement constr = constructorsIn(currentClass.getEnclosedElements()).get(0);
+ Trees trees = Trees.instance(processingEnv);
+ TreePath path = trees.getPath(constr);
+
+ new TreePathScanner() {
+ @Override public Void visitClass(ClassTree node, Void p) {
+ if (node.getSimpleName().contentEquals("Local")) {
+ //will also attribute the body on demand:
+ Element el = trees.getElement(getCurrentPath());
+ Name binaryName = elements.getBinaryName((TypeElement) el);
+ if (!binaryName.contentEquals("OnDemandAttributionData$1Local")) {
+ throw new IllegalStateException("Incorrect binary name=" + binaryName);
+ }
+ }
+ return super.visitClass(node, p);
+ }
+ @Override public Void visitNewClass(NewClassTree node, Void p) {
Element el = trees.getElement(getCurrentPath());
- Name binaryName = elements.getBinaryName((TypeElement) el);
- if (!binaryName.contentEquals("OnDemandAttribution$1Local")) {
+ Name binaryName = elements.getBinaryName((TypeElement) el.getEnclosingElement());
+ if (!binaryName.contentEquals("OnDemandAttributionData$1")) {
throw new IllegalStateException("Incorrect binary name=" + binaryName);
}
+ return super.visitNewClass(node, p);
}
- return super.visitClass(node, p);
- }
- @Override public Void visitNewClass(NewClassTree node, Void p) {
- Element el = trees.getElement(getCurrentPath());
- Name binaryName = elements.getBinaryName((TypeElement) el.getEnclosingElement());
- if (!binaryName.contentEquals("OnDemandAttribution$1")) {
- throw new IllegalStateException("Incorrect binary name=" + binaryName);
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
+ if (trees.getElement(getCurrentPath()) == null)
+ throw new IllegalStateException("No element for: " + node);
+ return super.visitMethodInvocation(node, p);
}
- return super.visitNewClass(node, p);
+ @Override
+ public Void visitIdentifier(IdentifierTree node, Void p) {
+ if (trees.getElement(getCurrentPath()) == null)
+ throw new IllegalStateException("No element for: " + node);
+ return super.visitIdentifier(node, p);
+ }
+ }.scan(path, null);
+ }
+
+ if (round++ == 0) {
+ try (Writer out = filer.createSourceFile("Gen").openWriter()) {
+ out.write("class Gen { public static long C = 1; }");
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
}
- }.scan(path, null);
+ }
return true;
}
diff --git a/langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java b/langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java
new file mode 100644
index 00000000000..3b986e30c35
--- /dev/null
+++ b/langtools/test/tools/javac/processing/model/trees/OnDemandAttributionData.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2016, 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.
+ */
+
+public class OnDemandAttributionData {
+
+ public OnDemandAttributionData(int i) {
+ class Local { }
+ new Aux(Gen.C) { };
+ }
+
+ class Aux {
+ Aux(String str) {}
+ Aux(int i) {}
+ Aux(long l) {}
+ }
+
+ private void methodAttributionTest() {
+ System.err.println("");
+ }
+
+ enum E {
+ A;
+
+ final int i;
+
+ E() {
+ i = Integer.parseInt("1");
+ }
+
+ }
+
+ enum E2 {
+ A;
+
+ {
+ int i = Integer.parseInt("1");
+ }
+ }
+}
From 4c6cbab8ba46014aea945c8d51ad63fba6ee4030 Mon Sep 17 00:00:00 2001
From: Andrey Nazarov
Date: Fri, 23 Sep 2016 09:57:24 -0700
Subject: [PATCH 079/114] 8166127: Develop new tests to cover javadoc module
options which are passed to underlying javac
Reviewed-by: jjg, ksrini
---
.../javadoc/tool/modules/ModuleTestBase.java | 8 +-
.../jdk/javadoc/tool/modules/Modules.java | 313 ++++++++++++++++--
2 files changed, 294 insertions(+), 27 deletions(-)
diff --git a/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java b/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java
index 5b3647ad0d7..a63350522a0 100644
--- a/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java
+++ b/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java
@@ -252,10 +252,14 @@ public class ModuleTestBase extends TestRunner {
}
void assertAbsent(String regex) throws Exception {
- List foundList = tb.grep(regex, currentTask.getOutputLines(STDOUT));
+ assertAbsent(regex, STDOUT);
+ }
+
+ void assertAbsent(String regex, Task.OutputKind kind) throws Exception {
+ List foundList = tb.grep(regex, currentTask.getOutputLines(kind));
if (!foundList.isEmpty()) {
dumpDocletDiagnostics();
- throw new Exception(regex + " found in: " + STDOUT);
+ throw new Exception(regex + " found in: " + kind);
}
}
diff --git a/langtools/test/jdk/javadoc/tool/modules/Modules.java b/langtools/test/jdk/javadoc/tool/modules/Modules.java
index 496a8e2c3cb..80fd88b69b2 100644
--- a/langtools/test/jdk/javadoc/tool/modules/Modules.java
+++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java
@@ -21,9 +21,9 @@
* questions.
*/
-/**
+/*
* @test
- * @bug 8159305
+ * @bug 8159305 8166127
* @summary Tests primarily the module graph computations.
* @modules
* jdk.javadoc/jdk.javadoc.internal.api
@@ -40,6 +40,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import toolbox.*;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
public class Modules extends ModuleTestBase {
@@ -54,8 +56,8 @@ public class Modules extends ModuleTestBase {
ModuleBuilder mb = new ModuleBuilder(tb, "m1");
mb.comment("The first module.")
.exports("pub")
- .classes("package pub; /** Klass A */ public class A {}")
- .classes("package pro; /** Klass B */ public class B {}")
+ .classes("package pub; /** Class A */ public class A {}")
+ .classes("package pro; /** Class B */ public class B {}")
.write(src);
execTask("--module-source-path", src.toString(),
"--module", "m1");
@@ -72,15 +74,15 @@ public class Modules extends ModuleTestBase {
mb1.comment("The first module.")
.exports("m1pub")
.requires("m2")
- .classes("package m1pub; /** Klass A */ public class A {}")
- .classes("package m1pro; /** Klass B */ public class B {}")
+ .classes("package m1pub; /** Class A */ public class A {}")
+ .classes("package m1pro; /** Class B */ public class B {}")
.write(src);
ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
mb2.comment("The second module.")
.exports("m2pub")
- .classes("package m2pub; /** Klass A */ public class A {}")
- .classes("package m2pro; /** Klass B */ public class B {}")
+ .classes("package m2pub; /** Class A */ public class A {}")
+ .classes("package m2pro; /** Class B */ public class B {}")
.write(src);
execTask("--module-source-path", src.toString(),
"--module", "m1,m2");
@@ -98,15 +100,15 @@ public class Modules extends ModuleTestBase {
mb1.comment("The first module.")
.exports("m1pub")
.requires("m2")
- .classes("package m1pub; /** Klass A */ public class A {}")
- .classes("package m1pro; /** Klass B */ public class B {}")
+ .classes("package m1pub; /** Class A */ public class A {}")
+ .classes("package m1pro; /** Class B */ public class B {}")
.write(src);
ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
mb2.comment("The second module.")
.exports("m2pub")
- .classes("package m2pub; /** Klass A */ public class A {}")
- .classes("package m2pro; /** Klass B */ public class B {}")
+ .classes("package m2pub; /** Class A */ public class A {}")
+ .classes("package m2pro; /** Class B */ public class B {}")
.write(src);
execTask("--module-source-path", src.toString(),
"--module", "m1",
@@ -117,7 +119,268 @@ public class Modules extends ModuleTestBase {
}
- /**
+ @Test
+ public void testModulePathOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class A */ public class A { }")
+ .build(modulePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .requires("m1")
+ .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }")
+ .write(src);
+ execTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--module", "m2");
+ checkModulesSpecified("m2");
+ checkPackagesIncluded("pkg2");
+ checkMembersSelected("pkg2.B.f");
+
+ // module path option "-p"
+ execTask("--module-source-path", src.toString(),
+ "-p", modulePath.toString(),
+ "--module", "m2");
+ // no module path
+ execNegativeTask("--module-source-path", src.toString(),
+ "--module", "m2");
+ assertErrorPresent("error: module not found: m1");
+ }
+
+ @Test
+ public void testUpgradeModulePathOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+ Path upgradePath = base.resolve("upgrades");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class A */ public class A { }")
+ .build(modulePath);
+
+ ModuleBuilder mbUpgrade = new ModuleBuilder(tb, "m1");
+ mbUpgrade.comment("Module on upgrade module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class C */ public class C { }")
+ .build(upgradePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .requires("m1")
+ .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.C f; }")
+ .write(src);
+ execTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--upgrade-module-path", upgradePath.toString(),
+ "--module", "m2");
+ checkModulesSpecified("m2");
+ checkPackagesIncluded("pkg2");
+ checkMembersSelected("pkg2.B.f");
+
+ // no upgrade module path
+ execNegativeTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--module", "m2");
+ assertErrorPresent("error: cannot find symbol");
+
+ // dependency from module path
+ ModuleBuilder mb3 = new ModuleBuilder(tb, "m3");
+ mb3.comment("The third module.")
+ .exports("pkg3")
+ .requires("m1")
+ .classes("package pkg3; /** Class Z */ public class Z { /** Field f */ public pkg1.A f; }")
+ .write(src);
+ execNegativeTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--upgrade-module-path", upgradePath.toString(),
+ "--module", "m3");
+ assertErrorPresent("Z.java:1: error: cannot find symbol");
+ }
+
+ @Test
+ public void testAddModulesOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class A */ public class A { }")
+ .build(modulePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .classes("package pkg2; /** @see pkg1.A */ public class B { }")
+ .write(src);
+
+ String log = new JavadocTask(tb)
+ .options("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--module", "m2")
+ .run(Expect.FAIL)
+ .writeAll()
+ .getOutput(OutputKind.DIRECT);
+ if (!log.contains("B.java:1: error: reference not found")) {
+ throw new Exception("Error not found");
+ }
+
+ new JavadocTask(tb)
+ .options("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--add-modules", "m1",
+ "--module", "m2")
+ .run()
+ .writeAll();
+ }
+
+ @Test
+ public void testLimitModulesOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .build(modulePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .requires("m1")
+ .classes("package pkg2; /** Class B */ public class B { }")
+ .write(src);
+
+ execNegativeTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--limit-modules", "java.base",
+ "--module", "m2");
+ assertErrorPresent("error: module not found: m1");
+ }
+
+ @Test
+ public void testAddExportsOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .classes("package pkg1; /** Class A */ public class A { }")
+ .build(modulePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .requires("m1")
+ .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }")
+ .write(src);
+ execTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--add-exports", "m1/pkg1=m2",
+ "--module", "m2");
+ checkModulesSpecified("m2");
+ checkPackagesIncluded("pkg2");
+ checkMembersSelected("pkg2.B.f");
+ }
+
+// @Test @ignore JDK-8166379
+ public void testPatchModuleOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+ Path patchPath = base.resolve("patch");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class A */ public class A { }")
+ .build(modulePath);
+
+ tb.writeJavaFiles(patchPath, "package pkg1; /** Class A */ public class A { public static int k; }");
+ new JavacTask(tb)
+ .files(patchPath.resolve("pkg1/A.java"))
+ .run();
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .requires("m1")
+ .classes("package pkg2; /** Class B */ public class B { /** Field f */ public int f = pkg1.A.k; }")
+ .write(src);
+ execTask("--module-source-path", src.toString(),
+ "--patch-module", "m1=" + patchPath.toString(),
+ "--module-path", modulePath.toString(),
+ "--module", "m2");
+ checkModulesSpecified("m2");
+ checkPackagesIncluded("pkg2");
+ checkMembersSelected("pkg2.B.f");
+ }
+
+ @Test
+ public void testAddReadsOption(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path modulePath = base.resolve("modules");
+
+ ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
+ mb1.comment("Module on module path.")
+ .exports("pkg1")
+ .classes("package pkg1; /** Class A */ public class A {}")
+ .build(modulePath);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module.")
+ .exports("pkg2")
+ .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f;}")
+ .write(src);
+ execTask("--module-source-path", src.toString(),
+ "--module-path", modulePath.toString(),
+ "--add-modules", "m1",
+ "--add-reads", "m2=m1",
+ "--module", "m2");
+ checkModulesSpecified("m2");
+ checkPackagesIncluded("pkg2");
+ checkMembersSelected("pkg2.B.f");
+ }
+
+ @Test
+ public void testModuleOptionsWithLegacy(Path base) throws Exception {
+ Files.createDirectory(base);
+ Path src = base.resolve("src");
+ Path classpath = base.resolve("classpath");
+ Path modulePath = base.resolve("modules");
+
+ tb.writeJavaFiles(classpath, "package pkg1; /** Class C */ public class C { }");
+ new JavacTask(tb)
+ .files(classpath.resolve("pkg1/C.java"))
+ .run();
+
+ ModuleBuilder mb = new ModuleBuilder(tb, "m1");
+ mb.comment("The first module.")
+ .exports("pub")
+ .classes("package pub; /** Class M */ public class M { }")
+ .build(modulePath);
+
+ tb.writeJavaFiles(src, "package pkg; /** Class L */ public class L { public pkg1.C f1; public pub.M f2; }");
+
+ execTask("--source-path", src.toString(),
+ "--class-path", classpath.toString(),
+ "--module-path", modulePath.toString(),
+ "--add-modules", "m1",
+ "pkg");
+ checkPackagesIncluded("pkg");
+ checkTypesIncluded("pkg.L");
+ checkMembersSelected("pkg.L.f1");
+ checkMembersSelected("pkg.L.f2");
+ assertAbsent("error", OutputKind.DIRECT);
+ }
+
+ /**
* Tests diamond graph, inspired by javac diamond tests.
*
*
@@ -262,48 +525,48 @@ public class Modules extends ModuleTestBase {
new ModuleBuilder(tb, "J")
.comment("The J module.")
.exports("openJ")
- .classes("package openJ; /** Klass J open. */ public class J { }")
- .classes("package closedJ; /** Klass J closed. */ public class J { }")
+ .classes("package openJ; /** Class J open. */ public class J { }")
+ .classes("package closedJ; /** Class J closed. */ public class J { }")
.write(src);
new ModuleBuilder(tb, "L")
.comment("The L module.")
.exports("openL")
.requiresPublic("P")
- .classes("package openL; /** Klass L open */ public class L { }")
- .classes("package closedL; /** Klass L closed */ public class L { }")
+ .classes("package openL; /** Class L open */ public class L { }")
+ .classes("package closedL; /** Class L closed */ public class L { }")
.write(src);
new ModuleBuilder(tb, "N")
.comment("The N module.")
.exports("openN")
.requiresPublic("O")
- .classes("package openN; /** Klass N open */ public class N { }")
- .classes("package closedN; /** Klass N closed */ public class N { }")
+ .classes("package openN; /** Class N open */ public class N { }")
+ .classes("package closedN; /** Class N closed */ public class N { }")
.write(src);
new ModuleBuilder(tb, "O")
.comment("The O module.")
.exports("openO")
.requires("J")
- .classes("package openO; /** Klass O open. */ public class O { openJ.J j; }")
- .classes("package closedO; /** Klass O closed. */ public class O { }")
+ .classes("package openO; /** Class O open. */ public class O { openJ.J j; }")
+ .classes("package closedO; /** Class O closed. */ public class O { }")
.write(src);
new ModuleBuilder(tb, "P")
.comment("The O module.")
.exports("openP")
.requires("J")
- .classes("package openP; /** Klass O open. */ public class O { openJ.J j; }")
- .classes("package closedP; /** Klass O closed. */ public class O { }")
+ .classes("package openP; /** Class O open. */ public class O { openJ.J j; }")
+ .classes("package closedP; /** Class O closed. */ public class O { }")
.write(src);
new ModuleBuilder(tb, "Q")
.comment("The Q module.")
.exports("openQ")
.requires("J")
- .classes("package openQ; /** Klass Q open. */ public class Q { openJ.J j; }")
- .classes("package closedQ; /** Klass Q closed. */ public class Q { }")
+ .classes("package openQ; /** Class Q open. */ public class Q { openJ.J j; }")
+ .classes("package closedQ; /** Class Q closed. */ public class Q { }")
.write(src);
}
From 9496149e05fc2d73bca12f2d659b842136f4dc80 Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Fri, 23 Sep 2016 13:14:14 -0700
Subject: [PATCH 080/114] 8166465:
CompletableFuture.minimalCompletionStage().toCompletableFuture() should be
non-minimal
Reviewed-by: martin, chegar, shade
---
.../util/concurrent/CompletableFuture.java | 17 ++
.../concurrent/tck/CompletableFutureTest.java | 228 +++++++++++++++---
2 files changed, 215 insertions(+), 30 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
index 5708af2653c..9946b128591 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
@@ -2559,6 +2559,13 @@ public class CompletableFuture implements Future, CompletionStage {
* exceptionally with a CompletionException with this exception as
* cause.
*
+ * Unless overridden by a subclass, a new non-minimal
+ * CompletableFuture with all methods available can be obtained from
+ * a minimal CompletionStage via {@link #toCompletableFuture()}.
+ * For example, completion of a minimal stage can be awaited by
+ *
+ *
{@code minimalStage.toCompletableFuture().join(); }
+ *
* @return the new CompletionStage
* @since 9
*/
@@ -2853,6 +2860,16 @@ public class CompletableFuture implements Future, CompletionStage {
@Override public CompletableFuture completeOnTimeout
(T value, long timeout, TimeUnit unit) {
throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture toCompletableFuture() {
+ Object r;
+ if ((r = result) != null)
+ return new CompletableFuture(encodeRelay(r));
+ else {
+ CompletableFuture d = new CompletableFuture<>();
+ unipush(new UniRelay(d, this));
+ return d;
+ }
+ }
}
// VarHandle mechanics
diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
index a29f50e0a24..12f7ee99b53 100644
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
@@ -388,7 +388,7 @@ public class CompletableFutureTest extends JSR166TestCase {
checkCompletedNormally(f, "test");
}
- abstract class CheckedAction {
+ abstract static class CheckedAction {
int invocationCount = 0;
final ExecutionMode m;
CheckedAction(ExecutionMode m) { this.m = m; }
@@ -400,7 +400,7 @@ public class CompletableFutureTest extends JSR166TestCase {
void assertInvoked() { assertEquals(1, invocationCount); }
}
- abstract class CheckedIntegerAction extends CheckedAction {
+ abstract static class CheckedIntegerAction extends CheckedAction {
Integer value;
CheckedIntegerAction(ExecutionMode m) { super(m); }
void assertValue(Integer expected) {
@@ -409,7 +409,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class IntegerSupplier extends CheckedAction
+ static class IntegerSupplier extends CheckedAction
implements Supplier
{
final Integer value;
@@ -428,7 +428,7 @@ public class CompletableFutureTest extends JSR166TestCase {
return (x == null) ? null : x + 1;
}
- class NoopConsumer extends CheckedIntegerAction
+ static class NoopConsumer extends CheckedIntegerAction
implements Consumer
{
NoopConsumer(ExecutionMode m) { super(m); }
@@ -438,7 +438,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class IncFunction extends CheckedIntegerAction
+ static class IncFunction extends CheckedIntegerAction
implements Function
{
IncFunction(ExecutionMode m) { super(m); }
@@ -456,7 +456,7 @@ public class CompletableFutureTest extends JSR166TestCase {
- ((y == null) ? 99 : y.intValue());
}
- class SubtractAction extends CheckedIntegerAction
+ static class SubtractAction extends CheckedIntegerAction
implements BiConsumer
{
SubtractAction(ExecutionMode m) { super(m); }
@@ -466,7 +466,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class SubtractFunction extends CheckedIntegerAction
+ static class SubtractFunction extends CheckedIntegerAction
implements BiFunction
{
SubtractFunction(ExecutionMode m) { super(m); }
@@ -476,14 +476,14 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class Noop extends CheckedAction implements Runnable {
+ static class Noop extends CheckedAction implements Runnable {
Noop(ExecutionMode m) { super(m); }
public void run() {
invoked();
}
}
- class FailingSupplier extends CheckedAction
+ static class FailingSupplier extends CheckedAction
implements Supplier
{
final CFException ex;
@@ -494,7 +494,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingConsumer extends CheckedIntegerAction
+ static class FailingConsumer extends CheckedIntegerAction
implements Consumer
{
final CFException ex;
@@ -506,7 +506,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingBiConsumer extends CheckedIntegerAction
+ static class FailingBiConsumer extends CheckedIntegerAction
implements BiConsumer
{
final CFException ex;
@@ -518,7 +518,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingFunction extends CheckedIntegerAction
+ static class FailingFunction extends CheckedIntegerAction
implements Function
{
final CFException ex;
@@ -530,7 +530,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingBiFunction extends CheckedIntegerAction
+ static class FailingBiFunction extends CheckedIntegerAction
implements BiFunction
{
final CFException ex;
@@ -542,7 +542,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingRunnable extends CheckedAction implements Runnable {
+ static class FailingRunnable extends CheckedAction implements Runnable {
final CFException ex;
FailingRunnable(ExecutionMode m) { super(m); ex = new CFException(); }
public void run() {
@@ -551,7 +551,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class CompletableFutureInc extends CheckedIntegerAction
+ static class CompletableFutureInc extends CheckedIntegerAction
implements Function>
{
CompletableFutureInc(ExecutionMode m) { super(m); }
@@ -564,7 +564,7 @@ public class CompletableFutureTest extends JSR166TestCase {
}
}
- class FailingCompletableFutureFunction extends CheckedIntegerAction
+ static class FailingCompletableFutureFunction extends CheckedIntegerAction
implements Function>
{
final CFException ex;
@@ -3604,29 +3604,53 @@ public class CompletableFutureTest extends JSR166TestCase {
* copy returns a CompletableFuture that is completed normally,
* with the same value, when source is.
*/
- public void testCopy() {
+ public void testCopy_normalCompletion() {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ for (Integer v1 : new Integer[] { 1, null })
+ {
CompletableFuture f = new CompletableFuture<>();
+ if (!createIncomplete) assertTrue(f.complete(v1));
CompletableFuture g = f.copy();
- checkIncomplete(f);
- checkIncomplete(g);
- f.complete(1);
- checkCompletedNormally(f, 1);
- checkCompletedNormally(g, 1);
- }
+ if (createIncomplete) {
+ checkIncomplete(f);
+ checkIncomplete(g);
+ assertTrue(f.complete(v1));
+ }
+ checkCompletedNormally(f, v1);
+ checkCompletedNormally(g, v1);
+ }}
/**
* copy returns a CompletableFuture that is completed exceptionally
* when source is.
*/
- public void testCopy2() {
- CompletableFuture f = new CompletableFuture<>();
- CompletableFuture g = f.copy();
- checkIncomplete(f);
- checkIncomplete(g);
+ public void testCopy_exceptionalCompletion() {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ {
CFException ex = new CFException();
- f.completeExceptionally(ex);
+ CompletableFuture f = new CompletableFuture<>();
+ if (!createIncomplete) f.completeExceptionally(ex);
+ CompletableFuture g = f.copy();
+ if (createIncomplete) {
+ checkIncomplete(f);
+ checkIncomplete(g);
+ f.completeExceptionally(ex);
+ }
checkCompletedExceptionally(f, ex);
checkCompletedWithWrappedException(g, ex);
+ }}
+
+ /**
+ * Completion of a copy does not complete its source.
+ */
+ public void testCopy_oneWayPropagation() {
+ CompletableFuture f = new CompletableFuture<>();
+ assertTrue(f.copy().complete(1));
+ assertTrue(f.copy().complete(null));
+ assertTrue(f.copy().cancel(true));
+ assertTrue(f.copy().cancel(false));
+ assertTrue(f.copy().completeExceptionally(new CFException()));
+ checkIncomplete(f);
}
/**
@@ -3991,7 +4015,10 @@ public class CompletableFutureTest extends JSR166TestCase {
.collect(Collectors.toList());
List> stages = new ArrayList<>();
- stages.add(new CompletableFuture().minimalCompletionStage());
+ CompletionStage min =
+ new CompletableFuture().minimalCompletionStage();
+ stages.add(min);
+ stages.add(min.thenApply(x -> x));
stages.add(CompletableFuture.completedStage(1));
stages.add(CompletableFuture.failedStage(new CFException()));
@@ -4027,6 +4054,131 @@ public class CompletableFutureTest extends JSR166TestCase {
throw new Error("Methods did not throw UOE: " + bugs);
}
+ /**
+ * minimalStage.toCompletableFuture() returns a CompletableFuture that
+ * is completed normally, with the same value, when source is.
+ */
+ public void testMinimalCompletionStage_toCompletableFuture_normalCompletion() {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ for (Integer v1 : new Integer[] { 1, null })
+ {
+ CompletableFuture f = new CompletableFuture<>();
+ CompletionStage minimal = f.minimalCompletionStage();
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ CompletableFuture g = minimal.toCompletableFuture();
+ if (createIncomplete) {
+ checkIncomplete(f);
+ checkIncomplete(g);
+ assertTrue(f.complete(v1));
+ }
+ checkCompletedNormally(f, v1);
+ checkCompletedNormally(g, v1);
+ }}
+
+ /**
+ * minimalStage.toCompletableFuture() returns a CompletableFuture that
+ * is completed exceptionally when source is.
+ */
+ public void testMinimalCompletionStage_toCompletableFuture_exceptionalCompletion() {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ {
+ CFException ex = new CFException();
+ CompletableFuture f = new CompletableFuture<>();
+ CompletionStage minimal = f.minimalCompletionStage();
+ if (!createIncomplete) f.completeExceptionally(ex);
+ CompletableFuture g = minimal.toCompletableFuture();
+ if (createIncomplete) {
+ checkIncomplete(f);
+ checkIncomplete(g);
+ f.completeExceptionally(ex);
+ }
+ checkCompletedExceptionally(f, ex);
+ checkCompletedWithWrappedException(g, ex);
+ }}
+
+ /**
+ * minimalStage.toCompletableFuture() gives mutable CompletableFuture
+ */
+ public void testMinimalCompletionStage_toCompletableFuture_mutable() {
+ for (Integer v1 : new Integer[] { 1, null })
+ {
+ CompletableFuture f = new CompletableFuture<>();
+ CompletionStage minimal = f.minimalCompletionStage();
+ CompletableFuture g = minimal.toCompletableFuture();
+ assertTrue(g.complete(v1));
+ checkCompletedNormally(g, v1);
+ checkIncomplete(f);
+ checkIncomplete(minimal.toCompletableFuture());
+ }}
+
+ /**
+ * minimalStage.toCompletableFuture().join() awaits completion
+ */
+ public void testMinimalCompletionStage_toCompletableFuture_join() throws Exception {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ for (Integer v1 : new Integer[] { 1, null })
+ {
+ CompletableFuture f = new CompletableFuture<>();
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ CompletionStage minimal = f.minimalCompletionStage();
+ if (createIncomplete) assertTrue(f.complete(v1));
+ assertEquals(v1, minimal.toCompletableFuture().join());
+ assertEquals(v1, minimal.toCompletableFuture().get());
+ checkCompletedNormally(minimal.toCompletableFuture(), v1);
+ }}
+
+ /**
+ * Completion of a toCompletableFuture copy of a minimal stage
+ * does not complete its source.
+ */
+ public void testMinimalCompletionStage_toCompletableFuture_oneWayPropagation() {
+ CompletableFuture f = new CompletableFuture<>();
+ CompletionStage g = f.minimalCompletionStage();
+ assertTrue(g.toCompletableFuture().complete(1));
+ assertTrue(g.toCompletableFuture().complete(null));
+ assertTrue(g.toCompletableFuture().cancel(true));
+ assertTrue(g.toCompletableFuture().cancel(false));
+ assertTrue(g.toCompletableFuture().completeExceptionally(new CFException()));
+ checkIncomplete(g.toCompletableFuture());
+ f.complete(1);
+ checkCompletedNormally(g.toCompletableFuture(), 1);
+ }
+
+ /** Demo utility method for external reliable toCompletableFuture */
+ static CompletableFuture toCompletableFuture(CompletionStage stage) {
+ CompletableFuture f = new CompletableFuture<>();
+ stage.handle((T t, Throwable ex) -> {
+ if (ex != null) f.completeExceptionally(ex);
+ else f.complete(t);
+ return null;
+ });
+ return f;
+ }
+
+ /** Demo utility method to join a CompletionStage */
+ static T join(CompletionStage stage) {
+ return toCompletableFuture(stage).join();
+ }
+
+ /**
+ * Joining a minimal stage "by hand" works
+ */
+ public void testMinimalCompletionStage_join_by_hand() {
+ for (boolean createIncomplete : new boolean[] { true, false })
+ for (Integer v1 : new Integer[] { 1, null })
+ {
+ CompletableFuture f = new CompletableFuture<>();
+ CompletionStage minimal = f.minimalCompletionStage();
+ CompletableFuture g = new CompletableFuture<>();
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ minimal.thenAccept((x) -> g.complete(x));
+ if (createIncomplete) assertTrue(f.complete(v1));
+ g.join();
+ checkCompletedNormally(g, v1);
+ checkCompletedNormally(f, v1);
+ assertEquals(v1, join(minimal));
+ }}
+
static class Monad {
static class ZeroException extends RuntimeException {
public ZeroException() { super("monadic zero"); }
@@ -4317,6 +4469,22 @@ public class CompletableFutureTest extends JSR166TestCase {
assertTrue(neverCompleted.thenRun(() -> {}).cancel(true));
}
+ /**
+ * Checks for garbage retention when MinimalStage.toCompletableFuture()
+ * is invoked many times.
+ * 8161600: Garbage retention when source CompletableFutures are never completed
+ *
+ * As of 2016-07, fails with OOME:
+ * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testToCompletableFutureGarbageRetention tck
+ */
+ public void testToCompletableFutureGarbageRetention() throws Throwable {
+ final int n = expensiveTests ? 900_000 : 10;
+ CompletableFuture neverCompleted = new CompletableFuture<>();
+ CompletionStage minimal = neverCompleted.minimalCompletionStage();
+ for (int i = 0; i < n; i++)
+ assertTrue(minimal.toCompletableFuture().cancel(true));
+ }
+
// static U join(CompletionStage stage) {
// CompletableFuture f = new CompletableFuture<>();
// stage.whenComplete((v, ex) -> {
From c9f268cc15689f01be36e4e8b2512166991da66b Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Fri, 23 Sep 2016 13:18:22 -0700
Subject: [PATCH 081/114] 8166057: [testbug] CoreThreadTimeOut still uses
hardcoded timeout
Reviewed-by: martin, chegar, shade
---
.../ThreadPoolExecutor/CoreThreadTimeOut.java | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java
index 088907cae77..a8bb4c29615 100644
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java
@@ -83,15 +83,18 @@ public class CoreThreadTimeOut {
tpe.allowCoreThreadTimeOut(true);
check(tpe.allowsCoreThreadTimeOut());
equal(countExecutorThreads(), 0);
- long t0 = System.nanoTime();
- for (int i = 0; i < threadCount; i++)
- tpe.submit(new Runnable() { public void run() {}});
- int count = countExecutorThreads();
- if (millisElapsedSince(t0) < timeoutMillis)
- equal(count, threadCount);
+ long startTime = System.nanoTime();
+ for (int i = 0; i < threadCount; i++) {
+ tpe.submit(() -> {});
+ int count = countExecutorThreads();
+ if (millisElapsedSince(startTime) < timeoutMillis)
+ equal(count, i + 1);
+ }
while (countExecutorThreads() > 0 &&
- millisElapsedSince(t0) < 10 * 1000);
+ millisElapsedSince(startTime) < LONG_DELAY_MS)
+ Thread.yield();
equal(countExecutorThreads(), 0);
+ check(millisElapsedSince(startTime) >= timeoutMillis);
tpe.shutdown();
check(tpe.allowsCoreThreadTimeOut());
check(tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
From edc7565f51768eeede4116a97993873beb400675 Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Fri, 23 Sep 2016 13:21:23 -0700
Subject: [PATCH 082/114] 8166059: JSR166TestCase.java fails with NPE in
dumpTestThreads on timeout
Reviewed-by: martin, chegar, shade
---
jdk/test/java/util/concurrent/tck/JSR166TestCase.java | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
index aaa97d8abcb..8a0360f9b99 100644
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
@@ -1032,14 +1032,17 @@ public class JSR166TestCase extends TestCase {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
System.err.println("------ stacktrace dump start ------");
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
- String name = info.getThreadName();
+ final String name = info.getThreadName();
+ String lockName;
if ("Signal Dispatcher".equals(name))
continue;
if ("Reference Handler".equals(name)
- && info.getLockName().startsWith("java.lang.ref.Reference$Lock"))
+ && (lockName = info.getLockName()) != null
+ && lockName.startsWith("java.lang.ref.Reference$Lock"))
continue;
if ("Finalizer".equals(name)
- && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock"))
+ && (lockName = info.getLockName()) != null
+ && lockName.startsWith("java.lang.ref.ReferenceQueue$Lock"))
continue;
if ("checkForWedgedTest".equals(name))
continue;
@@ -1783,7 +1786,7 @@ public class JSR166TestCase extends TestCase {
* A CyclicBarrier that uses timed await and fails with
* AssertionFailedErrors instead of throwing checked exceptions.
*/
- public class CheckedBarrier extends CyclicBarrier {
+ public static class CheckedBarrier extends CyclicBarrier {
public CheckedBarrier(int parties) { super(parties); }
public int await() {
From c7cf1788eda68ef66e97c71d6626c198f7d77db2 Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Fri, 23 Sep 2016 13:24:33 -0700
Subject: [PATCH 083/114] 8165919: Miscellaneous changes imported from jsr166
CVS 2016-09-21
Reviewed-by: martin, chegar, shade
---
.../java/util/concurrent/ForkJoinPool.java | 31 +++++++-------
.../concurrent/atomic/DoubleAccumulator.java | 40 ++++++++++---------
.../concurrent/atomic/LongAccumulator.java | 16 ++++----
.../util/Collections/EmptyNavigableMap.java | 3 --
.../util/Collections/EmptyNavigableSet.java | 3 +-
jdk/test/java/util/Deque/ChorusLine.java | 10 ++++-
.../java/util/PriorityQueue/ForgetMeNot.java | 6 ++-
.../util/PriorityQueue/PriorityQueueSort.java | 8 +++-
.../util/PriorityQueue/RemoveContains.java | 13 +++++-
.../concurrent/Executors/AutoShutdown.java | 2 -
.../tck/AtomicIntegerArrayTest.java | 12 +++---
.../concurrent/tck/AtomicLongArrayTest.java | 12 +++---
.../tck/ConcurrentSkipListMapTest.java | 2 +-
.../tck/ConcurrentSkipListSetTest.java | 3 +-
.../concurrent/tck/CyclicBarrierTest.java | 14 +++----
.../util/concurrent/tck/DelayQueueTest.java | 6 +--
.../util/concurrent/tck/ForkJoinPoolTest.java | 12 ++----
.../concurrent/tck/ScheduledExecutorTest.java | 13 +++---
.../java/util/concurrent/tck/TreeMapTest.java | 2 +-
.../java/util/concurrent/tck/TreeSetTest.java | 3 +-
20 files changed, 112 insertions(+), 99 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index e8f7ac614df..98524dedc23 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -1191,7 +1191,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* Default idle timeout value (in milliseconds) for the thread
* triggering quiescence to park waiting for new work
*/
- private static final long DEFAULT_KEEPALIVE = 60000L;
+ private static final long DEFAULT_KEEPALIVE = 60_000L;
/**
* Undershoot tolerance for idle timeouts
@@ -2303,7 +2303,6 @@ public class ForkJoinPool extends AbstractExecutorService {
throw new NullPointerException();
long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
- String prefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
long c = ((((long)(-corep) << TC_SHIFT) & TC_MASK) |
(((long)(-parallelism) << RC_SHIFT) & RC_MASK));
@@ -2315,8 +2314,8 @@ public class ForkJoinPool extends AbstractExecutorService {
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1; // power of two, including space for submission queues
+ this.workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
this.workQueues = new WorkQueue[n];
- this.workerNamePrefix = prefix;
this.factory = factory;
this.ueh = handler;
this.saturate = saturate;
@@ -2327,11 +2326,19 @@ public class ForkJoinPool extends AbstractExecutorService {
checkPermission();
}
+ private Object newInstanceFromSystemProperty(String property)
+ throws ReflectiveOperationException {
+ String className = System.getProperty(property);
+ return (className == null)
+ ? null
+ : ClassLoader.getSystemClassLoader().loadClass(className)
+ .getConstructor().newInstance();
+ }
+
/**
* Constructor for common pool using parameters possibly
* overridden by system properties
*/
- @SuppressWarnings("deprecation") // Class.newInstance
private ForkJoinPool(byte forCommonPoolOnly) {
int parallelism = -1;
ForkJoinWorkerThreadFactory fac = null;
@@ -2339,18 +2346,12 @@ public class ForkJoinPool extends AbstractExecutorService {
try { // ignore exceptions in accessing/parsing properties
String pp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.parallelism");
- String fp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.threadFactory");
- String hp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
if (pp != null)
parallelism = Integer.parseInt(pp);
- if (fp != null)
- fac = ((ForkJoinWorkerThreadFactory)ClassLoader.
- getSystemClassLoader().loadClass(fp).newInstance());
- if (hp != null)
- handler = ((UncaughtExceptionHandler)ClassLoader.
- getSystemClassLoader().loadClass(hp).newInstance());
+ fac = (ForkJoinWorkerThreadFactory) newInstanceFromSystemProperty(
+ "java.util.concurrent.ForkJoinPool.common.threadFactory");
+ handler = (UncaughtExceptionHandler) newInstanceFromSystemProperty(
+ "java.util.concurrent.ForkJoinPool.common.exceptionHandler");
} catch (Exception ignore) {
}
@@ -2373,8 +2374,8 @@ public class ForkJoinPool extends AbstractExecutorService {
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1;
- this.workQueues = new WorkQueue[n];
this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+ this.workQueues = new WorkQueue[n];
this.factory = fac;
this.ueh = handler;
this.saturate = null;
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
index f3e3531dbd9..0d0346f02d6 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -35,6 +35,9 @@
package java.util.concurrent.atomic;
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Double.longBitsToDouble;
+
import java.io.Serializable;
import java.util.function.DoubleBinaryOperator;
@@ -91,7 +94,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
double identity) {
this.function = accumulatorFunction;
- base = this.identity = Double.doubleToRawLongBits(identity);
+ base = this.identity = doubleToRawLongBits(identity);
}
/**
@@ -101,18 +104,19 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public void accumulate(double x) {
Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null ||
- (r = Double.doubleToRawLongBits
- (function.applyAsDouble
- (Double.longBitsToDouble(b = base), x))) != b && !casBase(b, r)) {
+ if ((as = cells) != null
+ || ((r = doubleToRawLongBits
+ (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
+ && !casBase(b, r))) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended =
- (r = Double.doubleToRawLongBits
- (function.applyAsDouble
- (Double.longBitsToDouble(v = a.value), x))) == v ||
- a.cas(v, r)))
+ if (as == null
+ || (m = as.length - 1) < 0
+ || (a = as[getProbe() & m]) == null
+ || !(uncontended =
+ ((r = doubleToRawLongBits
+ (function.applyAsDouble
+ (longBitsToDouble(v = a.value), x))) == v)
+ || a.cas(v, r)))
doubleAccumulate(x, function, uncontended);
}
}
@@ -128,12 +132,12 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public double get() {
Cell[] as = cells;
- double result = Double.longBitsToDouble(base);
+ double result = longBitsToDouble(base);
if (as != null) {
for (Cell a : as)
if (a != null)
result = function.applyAsDouble
- (result, Double.longBitsToDouble(a.value));
+ (result, longBitsToDouble(a.value));
}
return result;
}
@@ -168,12 +172,12 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
*/
public double getThenReset() {
Cell[] as = cells;
- double result = Double.longBitsToDouble(base);
+ double result = longBitsToDouble(base);
base = identity;
if (as != null) {
for (Cell a : as) {
if (a != null) {
- double v = Double.longBitsToDouble(a.value);
+ double v = longBitsToDouble(a.value);
a.reset(identity);
result = function.applyAsDouble(result, v);
}
@@ -267,9 +271,9 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* held by this proxy
*/
private Object readResolve() {
- double d = Double.longBitsToDouble(identity);
+ double d = longBitsToDouble(identity);
DoubleAccumulator a = new DoubleAccumulator(function, d);
- a.base = Double.doubleToRawLongBits(value);
+ a.base = doubleToRawLongBits(value);
return a;
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
index 939a4a2eed9..8c6e332ad79 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
@@ -103,14 +103,16 @@ public class LongAccumulator extends Striped64 implements Serializable {
*/
public void accumulate(long x) {
Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null ||
- (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
+ if ((as = cells) != null
+ || ((r = function.applyAsLong(b = base, x)) != b
+ && !casBase(b, r))) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended =
- (r = function.applyAsLong(v = a.value, x)) == v ||
- a.cas(v, r)))
+ if (as == null
+ || (m = as.length - 1) < 0
+ || (a = as[getProbe() & m]) == null
+ || !(uncontended =
+ (r = function.applyAsLong(v = a.value, x)) == v
+ || a.cas(v, r)))
longAccumulate(x, function, uncontended);
}
}
diff --git a/jdk/test/java/util/Collections/EmptyNavigableMap.java b/jdk/test/java/util/Collections/EmptyNavigableMap.java
index 5daf055786a..359d30f4ab6 100644
--- a/jdk/test/java/util/Collections/EmptyNavigableMap.java
+++ b/jdk/test/java/util/Collections/EmptyNavigableMap.java
@@ -33,7 +33,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
-import java.util.NoSuchElementException;
import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -41,10 +40,8 @@ import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import static org.testng.Assert.fail;
-import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertSame;
public class EmptyNavigableMap {
diff --git a/jdk/test/java/util/Collections/EmptyNavigableSet.java b/jdk/test/java/util/Collections/EmptyNavigableSet.java
index 7541f3d363b..afe216da8d7 100644
--- a/jdk/test/java/util/Collections/EmptyNavigableSet.java
+++ b/jdk/test/java/util/Collections/EmptyNavigableSet.java
@@ -41,10 +41,9 @@ import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import static org.testng.Assert.fail;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
public class EmptyNavigableSet {
diff --git a/jdk/test/java/util/Deque/ChorusLine.java b/jdk/test/java/util/Deque/ChorusLine.java
index 2a09c65ef50..9f0d6f89aa5 100644
--- a/jdk/test/java/util/Deque/ChorusLine.java
+++ b/jdk/test/java/util/Deque/ChorusLine.java
@@ -28,8 +28,14 @@
* @author Martin Buchholz
*/
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.LinkedBlockingDeque;
public class ChorusLine {
private interface Tweaker {
diff --git a/jdk/test/java/util/PriorityQueue/ForgetMeNot.java b/jdk/test/java/util/PriorityQueue/ForgetMeNot.java
index 7778d1d793d..6f9f65d529e 100644
--- a/jdk/test/java/util/PriorityQueue/ForgetMeNot.java
+++ b/jdk/test/java/util/PriorityQueue/ForgetMeNot.java
@@ -28,7 +28,11 @@
* @author Martin Buchholz
*/
-import java.util.*;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
+import java.util.Queue;
public class ForgetMeNot {
private static void checkQ(PriorityQueue q, Integer...elts) {
diff --git a/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java b/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java
index 206d6e815c5..24229639163 100644
--- a/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java
+++ b/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java
@@ -37,7 +37,13 @@
* @summary Checks that a priority queue returns elements in sorted order across various operations
*/
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Queue;
+import java.util.PriorityQueue;
public class PriorityQueueSort {
diff --git a/jdk/test/java/util/PriorityQueue/RemoveContains.java b/jdk/test/java/util/PriorityQueue/RemoveContains.java
index 4b5d5a93bf2..809478221dd 100644
--- a/jdk/test/java/util/PriorityQueue/RemoveContains.java
+++ b/jdk/test/java/util/PriorityQueue/RemoveContains.java
@@ -28,8 +28,17 @@
* @author Martin Buchholz
*/
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
public class RemoveContains {
static volatile int passed = 0, failed = 0;
diff --git a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java
index 7e34e28bded..95dd38c02cc 100644
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java
@@ -31,8 +31,6 @@
*/
import static java.util.concurrent.Executors.defaultThreadFactory;
-import static java.util.concurrent.Executors.newFixedThreadPool;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java
index d3d8f14f5c0..e12284063f1 100644
--- a/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java
+++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java
@@ -303,7 +303,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
class Counter extends CheckedRunnable {
final AtomicIntegerArray aa;
- volatile int counts;
+ int decs;
Counter(AtomicIntegerArray a) { aa = a; }
public void realRun() {
for (;;) {
@@ -314,7 +314,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
if (v != 0) {
done = false;
if (aa.compareAndSet(i, v, v - 1))
- ++counts;
+ decs++;
}
}
if (done)
@@ -334,13 +334,11 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
aa.set(i, countdown);
Counter c1 = new Counter(aa);
Counter c2 = new Counter(aa);
- Thread t1 = new Thread(c1);
- Thread t2 = new Thread(c2);
- t1.start();
- t2.start();
+ Thread t1 = newStartedThread(c1);
+ Thread t2 = newStartedThread(c2);
t1.join();
t2.join();
- assertEquals(c1.counts+c2.counts, SIZE * countdown);
+ assertEquals(c1.decs + c2.decs, SIZE * countdown);
}
/**
diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java
index bd74addbf7f..b312388dd6a 100644
--- a/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java
+++ b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java
@@ -302,7 +302,7 @@ public class AtomicLongArrayTest extends JSR166TestCase {
class Counter extends CheckedRunnable {
final AtomicLongArray aa;
- volatile long counts;
+ int decs;
Counter(AtomicLongArray a) { aa = a; }
public void realRun() {
for (;;) {
@@ -313,7 +313,7 @@ public class AtomicLongArrayTest extends JSR166TestCase {
if (v != 0) {
done = false;
if (aa.compareAndSet(i, v, v - 1))
- ++counts;
+ decs++;
}
}
if (done)
@@ -333,13 +333,11 @@ public class AtomicLongArrayTest extends JSR166TestCase {
aa.set(i, countdown);
Counter c1 = new Counter(aa);
Counter c2 = new Counter(aa);
- Thread t1 = new Thread(c1);
- Thread t2 = new Thread(c2);
- t1.start();
- t2.start();
+ Thread t1 = newStartedThread(c1);
+ Thread t2 = newStartedThread(c2);
t1.join();
t2.join();
- assertEquals(c1.counts+c2.counts, SIZE * countdown);
+ assertEquals(c1.decs + c2.decs, SIZE * countdown);
}
/**
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
index 515303e3e64..0b1faad2824 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
@@ -1024,7 +1024,7 @@ public class ConcurrentSkipListMapTest extends JSR166TestCase {
static NavigableMap newMap(Class cl) throws Exception {
NavigableMap result =
- (NavigableMap) cl.newInstance();
+ (NavigableMap) cl.getConstructor().newInstance();
assertEquals(0, result.size());
assertFalse(result.keySet().iterator().hasNext());
return result;
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
index 4ec79c8edd3..28c9f6bd81b 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
@@ -725,7 +725,8 @@ public class ConcurrentSkipListSetTest extends JSR166TestCase {
}
static NavigableSet newSet(Class cl) throws Exception {
- NavigableSet result = (NavigableSet) cl.newInstance();
+ NavigableSet result =
+ (NavigableSet) cl.getConstructor().newInstance();
assertEquals(0, result.size());
assertFalse(result.iterator().hasNext());
return result;
diff --git a/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java b/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java
index bfae2ee323b..8db1063dce9 100644
--- a/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java
+++ b/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java
@@ -40,6 +40,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -52,11 +53,6 @@ public class CyclicBarrierTest extends JSR166TestCase {
return new TestSuite(CyclicBarrierTest.class);
}
- private volatile int countAction;
- private class MyAction implements Runnable {
- public void run() { ++countAction; }
- }
-
/**
* Spin-waits till the number of waiters == numberOfWaiters.
*/
@@ -114,14 +110,16 @@ public class CyclicBarrierTest extends JSR166TestCase {
* The supplied barrier action is run at barrier
*/
public void testBarrierAction() throws Exception {
- countAction = 0;
- CyclicBarrier b = new CyclicBarrier(1, new MyAction());
+ final AtomicInteger count = new AtomicInteger(0);
+ final Runnable incCount = new Runnable() { public void run() {
+ count.getAndIncrement(); }};
+ CyclicBarrier b = new CyclicBarrier(1, incCount);
assertEquals(1, b.getParties());
assertEquals(0, b.getNumberWaiting());
b.await();
b.await();
assertEquals(0, b.getNumberWaiting());
- assertEquals(2, countAction);
+ assertEquals(2, count.get());
}
/**
diff --git a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
index 4d05c864554..d4a6bdc969c 100644
--- a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
@@ -121,10 +121,8 @@ public class DelayQueueTest extends JSR166TestCase {
}
public boolean equals(Object other) {
- return equals((NanoDelay)other);
- }
- public boolean equals(NanoDelay other) {
- return other.trigger == trigger;
+ return (other instanceof NanoDelay) &&
+ this.trigger == ((NanoDelay)other).trigger;
}
// suppress [overrides] javac warning
diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java b/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java
index 282557d97b7..70004764a78 100644
--- a/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java
+++ b/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java
@@ -51,6 +51,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import junit.framework.AssertionFailedError;
@@ -84,13 +85,6 @@ public class ForkJoinPoolTest extends JSR166TestCase {
// Some classes to test extension and factory methods
- static class MyHandler implements Thread.UncaughtExceptionHandler {
- volatile int catches = 0;
- public void uncaughtException(Thread t, Throwable e) {
- ++catches;
- }
- }
-
static class MyError extends Error {}
// to test handlers
@@ -101,9 +95,9 @@ public class ForkJoinPoolTest extends JSR166TestCase {
static class FailingThreadFactory
implements ForkJoinPool.ForkJoinWorkerThreadFactory {
- volatile int calls = 0;
+ final AtomicInteger calls = new AtomicInteger(0);
public ForkJoinWorkerThread newThread(ForkJoinPool p) {
- if (++calls > 1) return null;
+ if (calls.incrementAndGet() > 1) return null;
return new FailingFJWSubclass(p);
}
}
diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java
index 1cb2a472658..0946d006276 100644
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java
@@ -537,15 +537,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* isShutdown is false before shutdown, true after
*/
public void testIsShutdown() {
-
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
- try {
- assertFalse(p.isShutdown());
+ assertFalse(p.isShutdown());
+ try (PoolCleaner cleaner = cleaner(p)) {
+ try {
+ p.shutdown();
+ assertTrue(p.isShutdown());
+ } catch (SecurityException ok) {}
}
- finally {
- try { p.shutdown(); } catch (SecurityException ok) { return; }
- }
- assertTrue(p.isShutdown());
}
/**
diff --git a/jdk/test/java/util/concurrent/tck/TreeMapTest.java b/jdk/test/java/util/concurrent/tck/TreeMapTest.java
index ebf1dd01b9b..ada561ea119 100644
--- a/jdk/test/java/util/concurrent/tck/TreeMapTest.java
+++ b/jdk/test/java/util/concurrent/tck/TreeMapTest.java
@@ -829,7 +829,7 @@ public class TreeMapTest extends JSR166TestCase {
static NavigableMap newMap(Class cl) throws Exception {
NavigableMap result
- = (NavigableMap) cl.newInstance();
+ = (NavigableMap) cl.getConstructor().newInstance();
assertEquals(0, result.size());
assertFalse(result.keySet().iterator().hasNext());
return result;
diff --git a/jdk/test/java/util/concurrent/tck/TreeSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSetTest.java
index eb7b6efd9d0..dc5b007b0d3 100644
--- a/jdk/test/java/util/concurrent/tck/TreeSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/TreeSetTest.java
@@ -722,7 +722,8 @@ public class TreeSetTest extends JSR166TestCase {
}
static NavigableSet newSet(Class cl) throws Exception {
- NavigableSet result = (NavigableSet) cl.newInstance();
+ NavigableSet result =
+ (NavigableSet) cl.getConstructor().newInstance();
assertEquals(0, result.size());
assertFalse(result.iterator().hasNext());
return result;
From 4ca1072d25dcf21b1b852d41aceb80e6f76baf97 Mon Sep 17 00:00:00 2001
From: Robert Field
Date: Fri, 23 Sep 2016 14:37:03 -0700
Subject: [PATCH 084/114] 8166589: jshell tool: typo: remove out of place text
in /help /set truncation
Reviewed-by: jlahoda
---
.../classes/jdk/internal/jshell/tool/resources/l10n.properties | 1 -
1 file changed, 1 deletion(-)
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
index 7f7f12c0433..5434e949328 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
@@ -543,7 +543,6 @@ Set the max length a displayed value.\n\
\n\
Where is the name of a previously defined feedback mode -- see '/help /set mode'.\n\
Where is an unsigned integer representing a maximum length.\n\
-Where is a quoted string which will be the value of the field if one of\n\
Where is only needed if you wish to fine-tune value truncation length\n\
by context, is the context in which the truncation is applied.\n\
The structure of selector is a hyphen separated list of selector kind lists.\n\
From 414dc12887c66682a0090ccb8ca5eaa878ec5db1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?=
Date: Mon, 26 Sep 2016 13:27:45 +0200
Subject: [PATCH 085/114] 8164467: ES6 computed properties are implemented
wrongly
Reviewed-by: sundar, lagergren
---
.../internal/codegen/CodeGenerator.java | 57 ++++++++++------
.../jdk/nashorn/internal/ir/PropertyNode.java | 6 +-
.../jdk/nashorn/internal/parser/Parser.java | 30 +++++----
.../internal/runtime/ScriptObject.java | 12 ++--
.../basic/es6/computed-property-duplicate.js | 44 +++++++++++++
.../basic/es6/computed-property-getter.js | 66 +++++++++++++++++++
.../basic/es6/computed-property-method.js | 66 +++++++++++++++++++
.../basic/es6/computed-property-number.js | 54 +++++++++++++++
.../basic/es6/computed-property-setter.js | 43 ++++++++++++
.../script/basic/es6/computed-property.js | 66 +++++++++++++++++++
10 files changed, 404 insertions(+), 40 deletions(-)
create mode 100644 nashorn/test/script/basic/es6/computed-property-duplicate.js
create mode 100644 nashorn/test/script/basic/es6/computed-property-getter.js
create mode 100644 nashorn/test/script/basic/es6/computed-property-method.js
create mode 100644 nashorn/test/script/basic/es6/computed-property-number.js
create mode 100644 nashorn/test/script/basic/es6/computed-property-setter.js
create mode 100644 nashorn/test/script/basic/es6/computed-property.js
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
index f784b74ca5f..c9fa06880f9 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -2512,7 +2512,8 @@ final class CodeGenerator extends NodeOperatorVisitor elements = objectNode.getElements();
final List> tuples = new ArrayList<>();
- final List gettersSetters = new ArrayList<>();
+ // List below will contain getter/setter properties and properties with computed keys (ES6)
+ final List specialProperties = new ArrayList<>();
final int ccp = getCurrentContinuationEntryPoint();
final List ranges = objectNode.getSplitRanges();
@@ -2522,11 +2523,14 @@ final class CodeGenerator extends NodeOperatorVisitor valueType = (!useDualFields() || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
+ final Class> valueType = (!useDualFields() || isComputedOrAccessor || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
tuples.add(new MapTuple(key, symbol, Type.typeFor(valueType), value) {
@Override
public Class> getValueType() {
@@ -2590,26 +2594,41 @@ final class CodeGenerator extends NodeOperatorVisitor
Date: Mon, 26 Sep 2016 14:56:35 +0200
Subject: [PATCH 086/114] 8163102: Fix headless only configuration option
Reviewed-by: tbell
---
jdk/make/launcher/Launcher-java.desktop.gmk | 4 +-
jdk/make/launcher/Launcher-jdk.policytool.gmk | 4 +-
jdk/make/lib/Awt2dLibraries.gmk | 138 +++++++++---------
.../java.desktop/unix/native/libjawt/jawt.c | 5 +
4 files changed, 77 insertions(+), 74 deletions(-)
diff --git a/jdk/make/launcher/Launcher-java.desktop.gmk b/jdk/make/launcher/Launcher-java.desktop.gmk
index f9fa7d16c22..8cf4d79363e 100644
--- a/jdk/make/launcher/Launcher-java.desktop.gmk
+++ b/jdk/make/launcher/Launcher-java.desktop.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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 @@ include LauncherCommon.gmk
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, jdk, launcher/Launcher-java.desktop.gmk))
-ifndef BUILD_HEADLESS_ONLY
+ifeq ($(ENABLE_HEADLESS_ONLY), false)
$(eval $(call SetupBuildLauncher, appletviewer, \
MAIN_CLASS := sun.applet.Main, \
JAVA_ARGS := --add-modules ALL-DEFAULT, \
diff --git a/jdk/make/launcher/Launcher-jdk.policytool.gmk b/jdk/make/launcher/Launcher-jdk.policytool.gmk
index 26ec6a4b96a..a23b598b22b 100644
--- a/jdk/make/launcher/Launcher-jdk.policytool.gmk
+++ b/jdk/make/launcher/Launcher-jdk.policytool.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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,7 @@
include LauncherCommon.gmk
-ifndef BUILD_HEADLESS_ONLY
+ifeq ($(ENABLE_HEADLESS_ONLY), false)
$(eval $(call SetupBuildLauncher, policytool, \
MAIN_CLASS := sun.security.tools.policytool.PolicyTool, \
LIBS_unix := $(X_LIBS), \
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index c7d296bf907..4212cd9f652 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -280,7 +280,7 @@ TARGETS += $(BUILD_LIBAWT)
################################################################################
ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
- ifndef BUILD_HEADLESS_ONLY
+ ifeq ($(ENABLE_HEADLESS_ONLY), false)
LIBAWT_XAWT_DIRS := \
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt_xawt \
@@ -511,77 +511,75 @@ TARGETS += $(BUILD_LIBJAVAJPEG)
################################################################################
-ifeq ($(BUILD_HEADLESS), true)
- # Mac and Windows only use the native AWT lib, do not build libawt_headless
- ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),)
+# Mac and Windows only use the native AWT lib, do not build libawt_headless
+ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),)
- LIBAWT_HEADLESS_DIRS := $(JDK_TOPDIR)/src/java.desktop/unix/native/libawt_headless/awt \
- $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
- $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \
- $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/x11 \
- $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
- $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
- #
+ LIBAWT_HEADLESS_DIRS := $(JDK_TOPDIR)/src/java.desktop/unix/native/libawt_headless/awt \
+ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
+ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \
+ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/x11 \
+ $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
+ $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
+ #
- LIBAWT_HEADLESS_EXCLUDES := medialib
- LIBAWT_HEADLESS_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
- $(addprefix -I, $(LIBAWT_HEADLESS_DIRS)) \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image \
- -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
- -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
- -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \
- -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libsunwjdga/ \
- $(LIBJAVA_HEADER_FLAGS) \
- #
+ LIBAWT_HEADLESS_EXCLUDES := medialib
+ LIBAWT_HEADLESS_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
+ $(addprefix -I, $(LIBAWT_HEADLESS_DIRS)) \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image \
+ -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
+ -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \
+ -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libsunwjdga/ \
+ $(LIBJAVA_HEADER_FLAGS) \
+ #
- LIBAWT_HEADLESS_REORDER :=
- ifeq ($(OPENJDK_TARGET_OS), solaris)
- ifneq ($(OPENJDK_TARGET_CPU), x86_64)
- LIBAWT_HEADLESS_REORDER := $(JDK_TOPDIR)/make/mapfiles/libawt_headless/reorder-$(OPENJDK_TARGET_CPU)
- endif
+ LIBAWT_HEADLESS_REORDER :=
+ ifeq ($(OPENJDK_TARGET_OS), solaris)
+ ifneq ($(OPENJDK_TARGET_CPU), x86_64)
+ LIBAWT_HEADLESS_REORDER := $(JDK_TOPDIR)/make/mapfiles/libawt_headless/reorder-$(OPENJDK_TARGET_CPU)
endif
-
- $(eval $(call SetupNativeCompilation,BUILD_LIBAWT_HEADLESS, \
- LIBRARY := awt_headless, \
- OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(LIBAWT_HEADLESS_DIRS), \
- EXCLUDES := $(LIBAWT_HEADLESS_EXCLUDES), \
- OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) \
- -DHEADLESS=true \
- -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
- $(CUPS_CFLAGS) \
- $(X_CFLAGS) \
- $(LIBAWT_HEADLESS_CFLAGS), \
- DISABLED_WARNINGS_xlc := 1506-356, \
- DISABLED_WARNINGS_solstudio := E_EMPTY_TRANSLATION_UNIT, \
- MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libawt_headless/mapfile-vers, \
- LDFLAGS := $(LDFLAGS_JDKLIB) \
- $(call SET_SHARED_LIBRARY_ORIGIN), \
- LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
- LDFLAGS_linux := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
- LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
- REORDER := $(LIBAWT_HEADLESS_REORDER), \
- LIBS_unix := -lawt -ljvm -ljava, \
- LIBS_linux := $(LIBM) $(LIBDL), \
- LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \
- OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \
- ))
-
- # AIX warning explanation:
- # 1506-356 : (W) Compilation unit is empty.
- # This happens during the headless build
-
- $(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT)
-
- TARGETS += $(BUILD_LIBAWT_HEADLESS)
-
endif
+
+ $(eval $(call SetupNativeCompilation,BUILD_LIBAWT_HEADLESS, \
+ LIBRARY := awt_headless, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(LIBAWT_HEADLESS_DIRS), \
+ EXCLUDES := $(LIBAWT_HEADLESS_EXCLUDES), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) \
+ -DHEADLESS=true \
+ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
+ $(CUPS_CFLAGS) \
+ $(X_CFLAGS) \
+ $(LIBAWT_HEADLESS_CFLAGS), \
+ DISABLED_WARNINGS_xlc := 1506-356, \
+ DISABLED_WARNINGS_solstudio := E_EMPTY_TRANSLATION_UNIT, \
+ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libawt_headless/mapfile-vers, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
+ LDFLAGS_linux := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
+ LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
+ REORDER := $(LIBAWT_HEADLESS_REORDER), \
+ LIBS_unix := -lawt -ljvm -ljava, \
+ LIBS_linux := $(LIBM) $(LIBDL), \
+ LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \
+ ))
+
+ # AIX warning explanation:
+ # 1506-356 : (W) Compilation unit is empty.
+ # This happens during the headless build
+
+ $(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT)
+
+ TARGETS += $(BUILD_LIBAWT_HEADLESS)
+
endif
################################################################################
@@ -780,7 +778,7 @@ else # OPENJDK_TARGET_OS not windows
ifneq ($(OPENJDK_TARGET_OS), solaris)
JAWT_LIBS += -lawt
endif
- ifndef BUILD_HEADLESS_ONLY
+ ifeq ($(ENABLE_HEADLESS_ONLY), false)
JAWT_LIBS += -lawt_xawt
else
JAWT_LIBS += -lawt_headless
@@ -809,7 +807,7 @@ else # OPENJDK_TARGET_OS not windows
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjawt, \
))
- ifndef BUILD_HEADLESS_ONLY
+ ifeq ($(ENABLE_HEADLESS_ONLY), false)
$(BUILD_LIBJAWT): $(BUILD_LIBAWT_XAWT)
else
$(BUILD_LIBJAWT): $(INSTALL_LIBRARIES_HERE)/$(LIBRARY_PREFIX)awt_headless$(SHARED_LIBRARY_SUFFIX)
@@ -825,7 +823,7 @@ TARGETS += $(BUILD_LIBJAWT)
################################################################################
-ifndef BUILD_HEADLESS_ONLY
+ifeq ($(ENABLE_HEADLESS_ONLY), false)
LIBSPLASHSCREEN_DIRS := \
$(JDK_TOPDIR)/src/java.desktop/share/native/libjavajpeg \
diff --git a/jdk/src/java.desktop/unix/native/libjawt/jawt.c b/jdk/src/java.desktop/unix/native/libjawt/jawt.c
index 59e9a55cff2..ee61138dd31 100644
--- a/jdk/src/java.desktop/unix/native/libjawt/jawt.c
+++ b/jdk/src/java.desktop/unix/native/libjawt/jawt.c
@@ -39,6 +39,10 @@ DEF_STATIC_JNI_OnLoad
*/
JNIEXPORT jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt)
{
+#if defined(HEADLESS)
+ /* there are no AWT libs available at all */
+ return JNI_FALSE;
+#else
if (awt == NULL) {
return JNI_FALSE;
}
@@ -64,4 +68,5 @@ JNIEXPORT jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt)
}
return JNI_TRUE;
+#endif
}
From 12fae4c79f6a97590a031131f808b5980bea44d0 Mon Sep 17 00:00:00 2001
From: Erik Joelsson
Date: Mon, 26 Sep 2016 14:57:00 +0200
Subject: [PATCH 087/114] 8163102: Fix headless only configuration option
Reviewed-by: tbell
---
common/autoconf/generated-configure.sh | 67 +++++++++++---------------
common/autoconf/jdk-options.m4 | 39 ++++++---------
common/autoconf/libraries.m4 | 10 ++--
common/autoconf/spec.gmk.in | 8 +--
4 files changed, 48 insertions(+), 76 deletions(-)
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 5d6d6913fe2..796784ed18b 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -926,9 +926,7 @@ COMPRESS_JARS
INCLUDE_SA
UNLIMITED_CRYPTO
CACERTS_FILE
-BUILD_HEADLESS
-SUPPORT_HEADFUL
-SUPPORT_HEADLESS
+ENABLE_HEADLESS_ONLY
DEFAULT_MAKE_TARGET
OS_VERSION_MICRO
OS_VERSION_MINOR
@@ -1153,7 +1151,7 @@ with_sdk_name
with_conf_name
with_output_sync
with_default_make_target
-enable_headful
+enable_headless_only
with_cacerts_file
enable_unlimited_crypto
with_copyright_year
@@ -1976,8 +1974,7 @@ Optional Features:
[disabled]
--enable-debug set the debug level to fastdebug (shorthand for
--with-debug-level=fastdebug) [disabled]
- --disable-headful disable building headful support (graphical UI
- support) [enabled]
+ --enable-headless-only only build headless (no GUI) support [disabled]
--enable-unlimited-crypto
Enable unlimited crypto policy [disabled]
--disable-keep-packaged-modules
@@ -5095,7 +5092,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1474460325
+DATE_WHEN_GENERATED=1474894604
###############################################################################
#
@@ -24192,37 +24189,31 @@ fi
# We need build & target for this.
- # Should we build a JDK/JVM with headful support (ie a graphical ui)?
- # We always build headless support.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking headful support" >&5
-$as_echo_n "checking headful support... " >&6; }
- # Check whether --enable-headful was given.
-if test "${enable_headful+set}" = set; then :
- enableval=$enable_headful; SUPPORT_HEADFUL=${enable_headful}
-else
- SUPPORT_HEADFUL=yes
+ # Should we build a JDK without a graphical UI?
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking headless only" >&5
+$as_echo_n "checking headless only... " >&6; }
+ # Check whether --enable-headless-only was given.
+if test "${enable_headless_only+set}" = set; then :
+ enableval=$enable_headless_only;
fi
- SUPPORT_HEADLESS=yes
- BUILD_HEADLESS="BUILD_HEADLESS:=true"
-
- if test "x$SUPPORT_HEADFUL" = xyes; then
- # We are building both headful and headless.
- headful_msg="include support for both headful and headless"
+ if test "x$enable_headless_only" = "xyes"; then
+ ENABLE_HEADLESS_ONLY="true"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ elif test "x$enable_headless_only" = "xno"; then
+ ENABLE_HEADLESS_ONLY="false"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ elif test "x$enable_headless_only" = "x"; then
+ ENABLE_HEADLESS_ONLY="false"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ else
+ as_fn_error $? "--enable-headless-only can only take yes or no" "$LINENO" 5
fi
- if test "x$SUPPORT_HEADFUL" = xno; then
- # Thus we are building headless only.
- BUILD_HEADLESS="BUILD_HEADLESS:=true"
- headful_msg="headless only"
- fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $headful_msg" >&5
-$as_echo "$headful_msg" >&6; }
-
-
-
# Choose cacerts source file
@@ -53045,13 +53036,9 @@ $as_echo "yes" >&6; }
# No X11 support on windows or macosx
NEEDS_LIB_X11=false
else
- if test "x$SUPPORT_HEADFUL" = xno; then
- # No X11 support if building headless-only
- NEEDS_LIB_X11=false
- else
- # All other instances need X11
- NEEDS_LIB_X11=true
- fi
+ # All other instances need X11, even if building headless only, libawt still
+ # needs X11 headers.
+ NEEDS_LIB_X11=true
fi
# Check if cups is needed
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index d6aa389f3ae..8becdf3669c 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -134,32 +134,25 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_OPEN_OR_CUSTOM],
AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
[
- # Should we build a JDK/JVM with headful support (ie a graphical ui)?
- # We always build headless support.
- AC_MSG_CHECKING([headful support])
- AC_ARG_ENABLE([headful], [AS_HELP_STRING([--disable-headful],
- [disable building headful support (graphical UI support) @<:@enabled@:>@])],
- [SUPPORT_HEADFUL=${enable_headful}], [SUPPORT_HEADFUL=yes])
+ # Should we build a JDK without a graphical UI?
+ AC_MSG_CHECKING([headless only])
+ AC_ARG_ENABLE([headless-only], [AS_HELP_STRING([--enable-headless-only],
+ [only build headless (no GUI) support @<:@disabled@:>@])])
- SUPPORT_HEADLESS=yes
- BUILD_HEADLESS="BUILD_HEADLESS:=true"
-
- if test "x$SUPPORT_HEADFUL" = xyes; then
- # We are building both headful and headless.
- headful_msg="include support for both headful and headless"
+ if test "x$enable_headless_only" = "xyes"; then
+ ENABLE_HEADLESS_ONLY="true"
+ AC_MSG_RESULT([yes])
+ elif test "x$enable_headless_only" = "xno"; then
+ ENABLE_HEADLESS_ONLY="false"
+ AC_MSG_RESULT([no])
+ elif test "x$enable_headless_only" = "x"; then
+ ENABLE_HEADLESS_ONLY="false"
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_ERROR([--enable-headless-only can only take yes or no])
fi
- if test "x$SUPPORT_HEADFUL" = xno; then
- # Thus we are building headless only.
- BUILD_HEADLESS="BUILD_HEADLESS:=true"
- headful_msg="headless only"
- fi
-
- AC_MSG_RESULT([$headful_msg])
-
- AC_SUBST(SUPPORT_HEADLESS)
- AC_SUBST(SUPPORT_HEADFUL)
- AC_SUBST(BUILD_HEADLESS)
+ AC_SUBST(ENABLE_HEADLESS_ONLY)
# Choose cacerts source file
AC_ARG_WITH(cacerts-file, [AS_HELP_STRING([--with-cacerts-file],
diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4
index 1e408ef022b..3ca12d4da7d 100644
--- a/common/autoconf/libraries.m4
+++ b/common/autoconf/libraries.m4
@@ -42,13 +42,9 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
# No X11 support on windows or macosx
NEEDS_LIB_X11=false
else
- if test "x$SUPPORT_HEADFUL" = xno; then
- # No X11 support if building headless-only
- NEEDS_LIB_X11=false
- else
- # All other instances need X11
- NEEDS_LIB_X11=true
- fi
+ # All other instances need X11, even if building headless only, libawt still
+ # needs X11 headers.
+ NEEDS_LIB_X11=true
fi
# Check if cups is needed
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index c591a79d327..710cf70ab7c 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -241,12 +241,8 @@ BUILD_GTEST := @BUILD_GTEST@
# Control use of precompiled header in hotspot libjvm build
USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@
-# Should we compile support for running with a graphical UI? (ie headful)
-# Should we compile support for running without? (ie headless)
-SUPPORT_HEADFUL:=@SUPPORT_HEADFUL@
-SUPPORT_HEADLESS:=@SUPPORT_HEADLESS@
-# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
-@BUILD_HEADLESS@
+# Only build headless support or not
+ENABLE_HEADLESS_ONLY := @ENABLE_HEADLESS_ONLY@
# Legacy support
USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@
From 2d35d5bfc31121e1531089c20f066bac201e4754 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Mon, 26 Sep 2016 08:19:07 -0700
Subject: [PATCH 088/114] 8130657: com/sun/net/httpserver/Test5.java failed
with java.lang.RuntimeException: wrong string result 8085575:
java/net/Socket/InheritHandle.java fails intermittently with "Address already
in use"
Reviewed-by: dfuchs
---
jdk/test/com/sun/net/httpserver/Test5.java | 3 +-
.../java/net/MulticastSocket/TimeToLive.java | 39 ++++++++++---------
jdk/test/java/net/Socket/InheritHandle.java | 23 +++++++++--
3 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/jdk/test/com/sun/net/httpserver/Test5.java b/jdk/test/com/sun/net/httpserver/Test5.java
index b6d39439b7a..f704cf8ef42 100644
--- a/jdk/test/com/sun/net/httpserver/Test5.java
+++ b/jdk/test/com/sun/net/httpserver/Test5.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -145,6 +145,7 @@ public class Test5 extends Test {
socket.close();
s = new String (b,0,count, "ISO8859_1");
if (!compare (s, result)) {
+ System.err.println(" Expected [" + result + "]\n actual [" + s + "]");
throw new RuntimeException ("wrong string result");
}
}
diff --git a/jdk/test/java/net/MulticastSocket/TimeToLive.java b/jdk/test/java/net/MulticastSocket/TimeToLive.java
index 99f2641d5d8..009ff6d0eb3 100644
--- a/jdk/test/java/net/MulticastSocket/TimeToLive.java
+++ b/jdk/test/java/net/MulticastSocket/TimeToLive.java
@@ -37,26 +37,27 @@ public class TimeToLive {
static int[] bad_ttls = { -1, 256 };
public static void main(String[] args) throws Exception {
- MulticastSocket socket = new MulticastSocket();
- int ttl = socket.getTimeToLive();
- System.out.println("default ttl: " + ttl);
- for (int i = 0; i < new_ttls.length; i++) {
- socket.setTimeToLive(new_ttls[i]);
- if (!(new_ttls[i] == socket.getTimeToLive())) {
- throw new RuntimeException("test failure, set/get differ: " +
- new_ttls[i] + " / " +
- socket.getTimeToLive());
+ try (MulticastSocket socket = new MulticastSocket()) {
+ int ttl = socket.getTimeToLive();
+ System.out.println("default ttl: " + ttl);
+ for (int i = 0; i < new_ttls.length; i++) {
+ socket.setTimeToLive(new_ttls[i]);
+ if (!(new_ttls[i] == socket.getTimeToLive())) {
+ throw new RuntimeException("test failure, set/get differ: " +
+ new_ttls[i] + " / " +
+ socket.getTimeToLive());
+ }
}
- }
- for (int j = 0; j < bad_ttls.length; j++) {
- boolean exception = false;
- try {
- socket.setTimeToLive(bad_ttls[j]);
- } catch (IllegalArgumentException e) {
- exception = true;
- }
- if (!exception) {
- throw new RuntimeException("bad argument accepted: " + bad_ttls[j]);
+ for (int j = 0; j < bad_ttls.length; j++) {
+ boolean exception = false;
+ try {
+ socket.setTimeToLive(bad_ttls[j]);
+ } catch (IllegalArgumentException e) {
+ exception = true;
+ }
+ if (!exception) {
+ throw new RuntimeException("bad argument accepted: " + bad_ttls[j]);
+ }
}
}
}
diff --git a/jdk/test/java/net/Socket/InheritHandle.java b/jdk/test/java/net/Socket/InheritHandle.java
index 3fa57caa68e..9a9cddae683 100644
--- a/jdk/test/java/net/Socket/InheritHandle.java
+++ b/jdk/test/java/net/Socket/InheritHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
@author Chris Hegarty
*/
+import java.net.BindException;
import java.net.ServerSocket;
import java.io.File;
import java.io.IOException;
@@ -74,6 +75,11 @@ public class InheritHandle
} catch (IOException ioe) {
System.out.println("Cannot create process");
ioe.printStackTrace();
+ try {
+ ss.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
return;
}
@@ -85,9 +91,18 @@ public class InheritHandle
System.out.println("Now close the socket and try to create another" +
" one listening on the same port");
ss.close();
- ss = new ServerSocket(port);
- System.out.println("Second ServerSocket created successfully");
- ss.close();
+ int retries = 0;
+ while (retries < 5) {
+ try (ServerSocket s = new ServerSocket(port);) {
+ System.out.println("Second ServerSocket created successfully");
+ break;
+ } catch (BindException e) {
+ System.out.println("BindException \"" + e.getMessage() + "\", retrying...");
+ Thread.sleep(100L);
+ retries ++;
+ continue;
+ }
+ }
} catch (InterruptedException ie) {
} catch (IOException ioe) {
From b6e72d65aaa8c56206370ab4391de4efc6539795 Mon Sep 17 00:00:00 2001
From: Christoph Langer
Date: Mon, 26 Sep 2016 21:24:17 +0200
Subject: [PATCH 089/114] 8166604: nio: remove unneeded locals variables and
correct NPE
Reviewed-by: alanb
---
.../share/classes/sun/nio/ch/DatagramChannelImpl.java | 4 ----
.../java.base/share/classes/sun/nio/ch/SocketChannelImpl.java | 2 --
2 files changed, 6 deletions(-)
diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
index f063e13ac13..7f63ec88264 100644
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
@@ -328,8 +328,6 @@ class DatagramChannelImpl
public SocketAddress receive(ByteBuffer dst) throws IOException {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
- if (dst == null)
- throw new NullPointerException();
synchronized (readLock) {
ensureOpen();
// Socket was not bound before attempting receive
@@ -716,8 +714,6 @@ class DatagramChannelImpl
@Override
public DatagramChannel connect(SocketAddress sa) throws IOException {
- int localPort = 0;
-
synchronized(readLock) {
synchronized(writeLock) {
synchronized (stateLock) {
diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
index 856e0cf2fb6..8e21e522079 100644
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
@@ -616,8 +616,6 @@ class SocketChannelImpl
}
public boolean connect(SocketAddress sa) throws IOException {
- int localPort = 0;
-
synchronized (readLock) {
synchronized (writeLock) {
ensureOpenAndUnconnected();
From 87803ca0e84e9d6d21104afbbc8865e419f85c59 Mon Sep 17 00:00:00 2001
From: Robert Field
Date: Mon, 26 Sep 2016 13:18:11 -0700
Subject: [PATCH 090/114] 8166655: JShell: Process running JShell should not be
blocked from exit by non-daemon data-transfer threads
Reviewed-by: jlahoda
---
.../share/classes/jdk/jshell/execution/DemultiplexInput.java | 1 +
.../share/classes/jdk/jshell/execution/JDIEventHandler.java | 1 +
2 files changed, 2 insertions(+)
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DemultiplexInput.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DemultiplexInput.java
index 09912801f7b..5842ca9ca85 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DemultiplexInput.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DemultiplexInput.java
@@ -45,6 +45,7 @@ class DemultiplexInput extends Thread {
DemultiplexInput(InputStream input, Map io, Iterable closeList) {
super("output reader");
+ setDaemon(true);
this.delegate = new DataInputStream(input);
this.io = io;
this.closeList = closeList;
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java
index e6bd57583ed..180216e5ffc 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java
@@ -53,6 +53,7 @@ class JDIEventHandler implements Runnable {
this.vm = vm;
this.reportVMExit = reportVMExit;
this.thread = new Thread(this, "event-handler");
+ this.thread.setDaemon(true);
}
/**
From cf46ec878a69f576c6b10dd616ded8f1a5102ef8 Mon Sep 17 00:00:00 2001
From: Steve Drach
Date: Mon, 26 Sep 2016 13:37:10 -0700
Subject: [PATCH 091/114] 8153654: Update jdeps to be multi-release jar aware
Reviewed-by: mchung
---
jdk/src/java.base/share/classes/module-info.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
index f49111be646..11d53463dc8 100644
--- a/jdk/src/java.base/share/classes/module-info.java
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -166,6 +166,7 @@ module java.base {
jdk.charsets,
jdk.compiler,
jdk.jartool,
+ jdk.jdeps,
jdk.jlink,
jdk.net,
jdk.scripting.nashorn,
@@ -189,7 +190,8 @@ module java.base {
jdk.unsupported,
jdk.vm.ci;
exports jdk.internal.util.jar to
- jdk.jartool;
+ jdk.jartool,
+ jdk.jdeps;
exports jdk.internal.vm to
java.management,
jdk.jvmstat;
From 18b1c7cd8b84d85752c5b27ec1deab124f008a2a Mon Sep 17 00:00:00 2001
From: Steve Drach
Date: Mon, 26 Sep 2016 13:39:50 -0700
Subject: [PATCH 092/114] 8153654: Update jdeps to be multi-release jar aware
Reviewed-by: mchung
---
.../classes/com/sun/tools/jdeps/Analyzer.java | 2 +-
.../classes/com/sun/tools/jdeps/Archive.java | 4 +-
.../com/sun/tools/jdeps/ClassFileReader.java | 79 +++--
.../sun/tools/jdeps/JdepsConfiguration.java | 24 +-
.../com/sun/tools/jdeps/JdepsTask.java | 27 ++
.../tools/jdeps/MultiReleaseException.java | 69 +++++
.../com/sun/tools/jdeps/VersionHelper.java | 75 +++++
.../tools/jdeps/resources/jdeps.properties | 11 +-
.../test/tools/jdeps/MultiReleaseJar.java | 274 ++++++++++++++++++
.../tools/jdeps/mrjar/10/test/Version.java | 40 +++
.../tools/jdeps/mrjar/9/test/NonPublic.java | 30 ++
.../tools/jdeps/mrjar/9/test/Version.java | 36 +++
.../test/tools/jdeps/mrjar/base/p/Foo.java | 28 ++
.../tools/jdeps/mrjar/base/test/Version.java | 34 +++
.../test/tools/jdeps/mrjar/test/Main.java | 35 +++
.../test/tools/jdeps/mrjar/v10/q/Bar.java | 29 ++
.../test/tools/jdeps/mrjar/v10/q/Gee.java | 28 ++
.../test/tools/jdeps/mrjar/v9/p/Foo.java | 31 ++
.../test/tools/jdeps/mrjar/v9/q/Bar.java | 28 ++
19 files changed, 854 insertions(+), 30 deletions(-)
create mode 100644 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java
create mode 100644 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java
create mode 100644 langtools/test/tools/jdeps/MultiReleaseJar.java
create mode 100644 langtools/test/tools/jdeps/mrjar/10/test/Version.java
create mode 100644 langtools/test/tools/jdeps/mrjar/9/test/NonPublic.java
create mode 100644 langtools/test/tools/jdeps/mrjar/9/test/Version.java
create mode 100644 langtools/test/tools/jdeps/mrjar/base/p/Foo.java
create mode 100644 langtools/test/tools/jdeps/mrjar/base/test/Version.java
create mode 100644 langtools/test/tools/jdeps/mrjar/test/Main.java
create mode 100644 langtools/test/tools/jdeps/mrjar/v10/q/Bar.java
create mode 100644 langtools/test/tools/jdeps/mrjar/v10/q/Gee.java
create mode 100644 langtools/test/tools/jdeps/mrjar/v9/p/Foo.java
create mode 100644 langtools/test/tools/jdeps/mrjar/v9/q/Bar.java
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
index aeb712bbc90..d60eea8d35f 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
@@ -256,7 +256,7 @@ public class Analyzer {
// return classname or package name depending on the level
private String getLocationName(Location o) {
if (level == Type.CLASS || level == Type.VERBOSE) {
- return o.getClassName();
+ return VersionHelper.get(o.getClassName());
} else {
String pkg = o.getPackageName();
return pkg.isEmpty() ? "" : pkg;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
index fd5b9a2ed90..3233d61baef 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
@@ -45,9 +45,9 @@ import java.util.stream.Stream;
* Represents the source of the class files.
*/
public class Archive implements Closeable {
- public static Archive getInstance(Path p) {
+ public static Archive getInstance(Path p, Runtime.Version version) {
try {
- return new Archive(p, ClassFileReader.newInstance(p));
+ return new Archive(p, ClassFileReader.newInstance(p, version));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
index c1b4311a7f1..a72a5152d3c 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
@@ -29,6 +29,8 @@ import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Dependencies.ClassFileError;
+import jdk.internal.util.jar.VersionedStream;
+
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
@@ -50,6 +52,7 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import java.util.zip.ZipFile;
/**
* ClassFileReader reads ClassFile(s) of a given path that can be
@@ -60,6 +63,13 @@ public class ClassFileReader implements Closeable {
* Returns a ClassFileReader instance of a given path.
*/
public static ClassFileReader newInstance(Path path) throws IOException {
+ return newInstance(path, JarFile.baseVersion());
+ }
+
+ /**
+ * Returns a ClassFileReader instance of a given path.
+ */
+ public static ClassFileReader newInstance(Path path, Runtime.Version version) throws IOException {
if (Files.notExists(path)) {
throw new FileNotFoundException(path.toString());
}
@@ -67,19 +77,12 @@ public class ClassFileReader implements Closeable {
if (Files.isDirectory(path)) {
return new DirectoryReader(path);
} else if (path.getFileName().toString().endsWith(".jar")) {
- return new JarFileReader(path);
+ return new JarFileReader(path, version);
} else {
return new ClassFileReader(path);
}
}
- /**
- * Returns a ClassFileReader instance of a given JarFile.
- */
- public static ClassFileReader newInstance(Path path, JarFile jf) throws IOException {
- return new JarFileReader(path, jf);
- }
-
/**
* Returns a ClassFileReader instance of a given FileSystem and path.
*
@@ -302,13 +305,16 @@ public class ClassFileReader implements Closeable {
static class JarFileReader extends ClassFileReader {
private final JarFile jarfile;
- JarFileReader(Path path) throws IOException {
- this(path, new JarFile(path.toFile(), false));
+ private final Runtime.Version version;
+
+ JarFileReader(Path path, Runtime.Version version) throws IOException {
+ this(path, openJarFile(path.toFile(), version), version);
}
- JarFileReader(Path path, JarFile jf) throws IOException {
+ JarFileReader(Path path, JarFile jf, Runtime.Version version) throws IOException {
super(path);
this.jarfile = jf;
+ this.version = version;
}
@Override
@@ -316,9 +322,26 @@ public class ClassFileReader implements Closeable {
jarfile.close();
}
+ private static JarFile openJarFile(File f, Runtime.Version version)
+ throws IOException {
+ JarFile jf;
+ if (version == null) {
+ jf = new JarFile(f, false);
+ if (jf.isMultiRelease()) {
+ throw new MultiReleaseException("err.multirelease.option.notfound", f.getName());
+ }
+ } else {
+ jf = new JarFile(f, false, ZipFile.OPEN_READ, version);
+ if (!jf.isMultiRelease()) {
+ throw new MultiReleaseException("err.multirelease.option.exists", f.getName());
+ }
+ }
+ return jf;
+ }
+
protected Set scan() {
- try (JarFile jf = new JarFile(path.toFile())) {
- return jf.stream().map(JarEntry::getName)
+ try (JarFile jf = openJarFile(path.toFile(), version)) {
+ return VersionedStream.stream(jf).map(JarEntry::getName)
.filter(n -> n.endsWith(".class"))
.collect(Collectors.toSet());
} catch (IOException e) {
@@ -348,15 +371,14 @@ public class ClassFileReader implements Closeable {
}
protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException {
- InputStream is = null;
- try {
- is = jarfile.getInputStream(e);
- return ClassFile.read(is);
+ try (InputStream is = jarfile.getInputStream(e)) {
+ ClassFile cf = ClassFile.read(is);
+ if (jarfile.isMultiRelease()) {
+ VersionHelper.add(jarfile, e, cf);
+ }
+ return cf;
} catch (ConstantPoolException ex) {
throw new ClassFileError(ex);
- } finally {
- if (is != null)
- is.close();
}
}
@@ -370,6 +392,21 @@ public class ClassFileReader implements Closeable {
}
}
+ Enumeration versionedEntries(JarFile jf) {
+ Iterator it = VersionedStream.stream(jf).iterator();
+ return new Enumeration<>() {
+ @Override
+ public boolean hasMoreElements() {
+ return it.hasNext();
+ }
+
+ @Override
+ public JarEntry nextElement() {
+ return it.next();
+ }
+ };
+ }
+
class JarFileIterator implements Iterator {
protected final JarFileReader reader;
protected Enumeration entries;
@@ -388,7 +425,7 @@ public class ClassFileReader implements Closeable {
if (jarfile == null) return;
this.jf = jarfile;
- this.entries = jf.entries();
+ this.entries = versionedEntries(jf);
this.nextEntry = nextEntry();
}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
index 3c4632a8078..b6640b1a4ba 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
@@ -81,19 +81,22 @@ public class JdepsConfiguration implements AutoCloseable {
private final List initialArchives = new ArrayList<>();
private final Set rootModules = new HashSet<>();
private final Configuration configuration;
+ private final Runtime.Version version;
private JdepsConfiguration(SystemModuleFinder systemModulePath,
ModuleFinder finder,
Set roots,
List classpaths,
List initialArchives,
- boolean allDefaultModules)
+ boolean allDefaultModules,
+ Runtime.Version version)
throws IOException
{
trace("root: %s%n", roots);
this.system = systemModulePath;
this.finder = finder;
+ this.version = version;
// build root set for resolution
Set mods = new HashSet<>(roots);
@@ -121,7 +124,7 @@ public class JdepsConfiguration implements AutoCloseable {
// classpath archives
for (Path p : classpaths) {
if (Files.exists(p)) {
- Archive archive = Archive.getInstance(p);
+ Archive archive = Archive.getInstance(p, version);
addPackagesInUnnamedModule(archive);
classpathArchives.add(archive);
}
@@ -292,7 +295,7 @@ public class JdepsConfiguration implements AutoCloseable {
if (location.getScheme().equals("jrt")) {
reader = system.getClassReader(mn);
} else {
- reader = ClassFileReader.newInstance(Paths.get(location));
+ reader = ClassFileReader.newInstance(Paths.get(location), version);
}
builder.classes(reader);
@@ -304,6 +307,10 @@ public class JdepsConfiguration implements AutoCloseable {
}
}
+ public Runtime.Version getVersion() {
+ return version;
+ }
+
/*
* Close all archives e.g. JarFile
*/
@@ -476,6 +483,7 @@ public class JdepsConfiguration implements AutoCloseable {
ModuleFinder appModulePath;
boolean addAllApplicationModules;
boolean addAllDefaultModules;
+ Runtime.Version version;
public Builder() {
this.systemModulePath = new SystemModuleFinder();
@@ -526,8 +534,13 @@ public class JdepsConfiguration implements AutoCloseable {
return this;
}
+ public Builder multiRelease(Runtime.Version version) {
+ this.version = version;
+ return this;
+ }
+
public Builder addRoot(Path path) {
- Archive archive = Archive.getInstance(path);
+ Archive archive = Archive.getInstance(path, version);
if (archive.contains(MODULE_INFO)) {
paths.add(path);
} else {
@@ -569,7 +582,8 @@ public class JdepsConfiguration implements AutoCloseable {
rootModules,
classPaths,
initialArchives,
- addAllDefaultModules);
+ addAllDefaultModules,
+ version);
}
private static ModuleFinder createModulePathFinder(String mpaths) {
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
index 38e1d08c6ef..862c5261859 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
@@ -36,6 +36,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.*;
+import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -389,6 +390,23 @@ class JdepsTask {
}
}
},
+ new Option(true, "--multi-release") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ if (arg.equalsIgnoreCase("base")) {
+ task.options.multiRelease = JarFile.baseVersion();
+ } else {
+ try {
+ int v = Integer.parseInt(arg);
+ if (v < 9) {
+ throw new BadArgs("err.invalid.arg.for.option", arg);
+ }
+ } catch (NumberFormatException x) {
+ throw new BadArgs("err.invalid.arg.for.option", arg);
+ }
+ task.options.multiRelease = Runtime.Version.parse(arg);
+ }
+ }
+ },
};
private static final String PROGNAME = "jdeps";
@@ -481,6 +499,9 @@ class JdepsTask {
} catch (IOException e) {
e.printStackTrace();
return EXIT_CMDERR;
+ } catch (MultiReleaseException e) {
+ reportError(e.getKey(), (Object)e.getMsg());
+ return EXIT_CMDERR; // could be EXIT_ABNORMAL sometimes
} finally {
log.flush();
}
@@ -541,11 +562,16 @@ class JdepsTask {
if (options.classpath != null)
builder.addClassPath(options.classpath);
+ if (options.multiRelease != null)
+ builder.multiRelease(options.multiRelease);
+
// build the root set of archives to be analyzed
for (String s : inputArgs) {
Path p = Paths.get(s);
if (Files.exists(p)) {
builder.addRoot(p);
+ } else {
+ warning("warn.invalid.arg", s);
}
}
@@ -839,6 +865,7 @@ class JdepsTask {
String modulePath;
String rootModule;
Set addmods = new HashSet<>();
+ Runtime.Version multiRelease;
boolean hasFilter() {
return numFilters() > 0;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java
new file mode 100644
index 00000000000..feb35989334
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, 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 com.sun.tools.jdeps;
+
+/**
+ * Signals that an exception of some sort has occurred while processing
+ * a multi-release jar file.
+ *
+ * @since 9
+ */
+class MultiReleaseException extends RuntimeException {
+ private static final long serialVersionUID = 4474870142461654108L;
+ private final String key;
+ private final String[] msg;
+
+ /**
+ * Constructs an {@code MultiReleaseException} with the specified detail
+ * error message array.
+ *
+ * @param key
+ * The key that identifies the message in the jdeps.properties file
+ * @param msg
+ * The detail message array
+ */
+ public MultiReleaseException(String key, String... msg) {
+ super();
+ this.key = key;
+ this.msg = msg;
+ }
+
+ /**
+ * Returns the resource message key
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Returns the detailed error message array.
+ *
+ * @return the detailed error message array
+ */
+ public String[] getMsg() {
+ return msg;
+ }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java
new file mode 100644
index 00000000000..b94d87c1397
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, 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 com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import jdk.internal.misc.SharedSecrets;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public class VersionHelper {
+ private static final String META_INF_VERSIONS = "META-INF/versions/";
+ private static final Map nameToVersion = new ConcurrentHashMap<>();
+
+ public static String get(String classname) {
+ if (nameToVersion.containsKey(classname)) {
+ return nameToVersion.get(classname) + "/" + classname;
+ }
+ return classname;
+ }
+
+ public static void add(JarFile jarfile, JarEntry e, ClassFile cf)
+ throws ConstantPoolException
+ {
+ String realName = SharedSecrets.javaUtilJarAccess().getRealName(jarfile, e);
+ if (realName.startsWith(META_INF_VERSIONS)) {
+ int len = META_INF_VERSIONS.length();
+ int n = realName.indexOf('/', len);
+ if (n > 0) {
+ String version = realName.substring(len, n);
+ assert (Integer.parseInt(version) > 8);
+ String name = cf.getName().replace('/', '.');
+ if (nameToVersion.containsKey(name)) {
+ if (!version.equals(nameToVersion.get(name))) {
+ throw new MultiReleaseException(
+ "err.multirelease.version.associated",
+ name, nameToVersion.get(name), version
+ );
+ }
+ } else {
+ nameToVersion.put(name, version);
+ }
+ } else {
+ throw new MultiReleaseException("err.multirelease.jar.malformed",
+ jarfile.getName(), realName);
+ }
+ }
+ }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
index 571126c7383..821c99d54e9 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
@@ -150,6 +150,11 @@ main.opt.q=\
\ -q -quiet Do not show missing dependencies from \n\
\ -genmoduleinfo output.
+main.opt.multi-release=\
+\ --multi-release Specifies the version when processing\n\
+\ multi-release jar files. should\n\
+\ be integer >= 9 or base.
+
err.unknown.option=unknown option: {0}
err.missing.arg=no value given for {0}
err.invalid.arg.for.option=invalid argument for option: {0}
@@ -164,7 +169,11 @@ err.module.not.found=module not found: {0}
err.root.module.not.set=root module set empty
err.invalid.inverse.option={0} cannot be used with -inverse option
err.inverse.filter.not.set={0} cannot be used with -inverse option
-warn.invalid.arg=Path not exist: {0}
+err.multirelease.option.exists={0} is not a multi-release jar file, but the --multi-release option is set
+err.multirelease.option.notfound={0} is a multi-release jar file, but the --multi-release option is not set
+err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2}
+err.multirelease.jar.malformed=malformed multi-release jar, {0}, bad entry: {1}
+warn.invalid.arg=Path does not exist: {0}
warn.split.package=package {0} defined in {1} {2}
warn.replace.useJDKInternals=\
JDK internal APIs are unsupported and private to JDK implementation that are\n\
diff --git a/langtools/test/tools/jdeps/MultiReleaseJar.java b/langtools/test/tools/jdeps/MultiReleaseJar.java
new file mode 100644
index 00000000000..0f4fd7cc405
--- /dev/null
+++ b/langtools/test/tools/jdeps/MultiReleaseJar.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2016, 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 8153654
+ * @summary Tests for jdeps tool with multi-release jar files
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @library mrjar mrjar/base mrjar/9 mrjar/10 mrjar/v9 mrjar/v10
+ * @build test.* p.* q.*
+ * @run testng MultiReleaseJar
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeUnit;
+
+public class MultiReleaseJar {
+ Path mrjar;
+ String testJdk;
+ String fileSep;
+ Path cmdPath;
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ mrjar = Paths.get(System.getProperty("test.classes", "."), "mrjar");
+ testJdk = System.getProperty("test.jdk");
+ fileSep = System.getProperty("file.separator");
+ cmdPath = Paths.get(testJdk, "bin");
+ }
+
+ @Test
+ public void basic() throws Exception {
+ // build the jar file
+ Result r = run("jar -cf Version.jar -C base test --release 9 -C 9 test --release 10 -C 10 test");
+ checkResult(r);
+
+ // try out a bunch of things
+ r = run("jdeps --multi-release 9 -v missing.jar");
+ checkResult(r, false, "Warning: Path does not exist: missing.jar");
+
+ r = run("jdeps -v Version.jar");
+ checkResult(r, false, "the --multi-release option is not set");
+
+ r = run("jdeps --multi-release base -v Version.jar");
+ checkResult(r, true,
+ "Version.jar ->",
+ "test.Version",
+ "test.Version"
+ );
+
+ r = run("jdeps --multi-release 9 -v Version.jar");
+ checkResult(r, true,
+ "Version.jar ->",
+ "9/test.NonPublic",
+ "9/test.NonPublic",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version"
+ );
+
+ r = run("jdeps --multi-release 10 -v Version.jar");
+ checkResult(r, true,
+ "Version.jar ->",
+ "10/test.Version",
+ "10/test.Version",
+ "10/test.Version",
+ "10/test.Version",
+ "9/test.NonPublic",
+ "9/test.NonPublic"
+ );
+
+ r = run("jdeps --multi-release 8 -v Version.jar");
+ checkResult(r, false, "Error: invalid argument for option: 8");
+
+ r = run("jdeps --multi-release 9.1 -v Version.jar");
+ checkResult(r, false, "Error: invalid argument for option: 9.1");
+
+ r = run("jdeps -v -R -cp Version.jar test/Main.class");
+ checkResult(r, false, "the --multi-release option is not set");
+
+ r = run("jdeps -v -R -cp Version.jar -multi-release 9 test/Main.class");
+ checkResult(r, false,
+ "Error: unknown option: -multi-release",
+ "Usage: jdeps ",
+ "Main.class ->",
+ "test.Main",
+ "test.Main",
+ "test.Main",
+ "Version.jar ->",
+ "9/test.NonPublic",
+ "9/test.NonPublic",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version"
+ );
+
+ r = run("jdeps -v -R -cp Version.jar --multi-release 10 test/Main.class");
+ checkResult(r, true,
+ "Main.class ->",
+ "Main.class ->",
+ "test.Main",
+ "test.Main",
+ "test.Main",
+ "Version.jar ->",
+ "10/test.Version",
+ "10/test.Version",
+ "10/test.Version",
+ "10/test.Version",
+ "9/test.NonPublic",
+ "9/test.NonPublic"
+ );
+
+ r = run("jdeps -v -R -cp Version.jar --multi-release base test/Main.class");
+ checkResult(r, true,
+ "Main.class ->",
+ "Main.class ->",
+ "test.Main",
+ "test.Main",
+ "test.Main",
+ "Version.jar ->",
+ "test.Version",
+ "test.Version"
+ );
+
+ r = run("jdeps -v -R -cp Version.jar --multi-release 9.1 test/Main.class");
+ checkResult(r, false, "Error: invalid argument for option: 9.1");
+
+ // Rebuild jar without version 10
+ r = run("jar -cf Version.jar -C base test --release 9 -C 9 test");
+ checkResult(r);
+
+ // but ask for version 10
+ r = run("jdeps -v -R -cp Version.jar --multi-release 10 test/Main.class");
+ checkResult(r, true,
+ "Main.class ->",
+ "Main.class ->",
+ "test.Main",
+ "test.Main",
+ "test.Main",
+ "Version.jar ->",
+ "9/test.NonPublic",
+ "9/test.NonPublic",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version",
+ "9/test.Version"
+ );
+ }
+
+ @Test
+ public void ps_and_qs() throws Exception {
+ // build the jar file
+ Result r = run("jar -cf PQ.jar -C base p --release 9 -C v9 p -C v9 q --release 10 -C v10 q");
+ checkResult(r);
+
+ r = run("jdeps -v -R -cp PQ.jar --multi-release base PQ.jar");
+ checkResult(r, true,
+ "PQ.jar -> java.base",
+ "p.Foo"
+ );
+
+ r = run("jdeps -v -R -cp PQ.jar --multi-release 9 PQ.jar");
+ checkResult(r, true,
+ "PQ.jar -> java.base",
+ "9/p.Foo",
+ "9/p.Foo",
+ "9/q.Bar"
+ );
+
+
+ r = run("jdeps -v -R -cp PQ.jar --multi-release 10 PQ.jar");
+ checkResult(r, true,
+ "PQ.jar -> java.base",
+ "10/q.Bar",
+ "10/q.Bar",
+ "10/q.Gee",
+ "9/p.Foo",
+ "9/p.Foo"
+ );
+ }
+
+ static class Result {
+ final String cmd;
+ final int rc;
+ final String out;
+ final String err;
+ Result(String cmd, int rc, String out, String err) {
+ this.cmd = cmd;
+ this.rc = rc;
+ this.out = out;
+ this.err = err;
+ }
+ }
+
+ Result run(String cmd) throws Exception {
+ String[] cmds = cmd.split(" +");
+ cmds[0] = cmdPath.resolve(cmds[0]).toString();
+ ProcessBuilder pb = new ProcessBuilder(cmds);
+ pb.directory(mrjar.toFile());
+ Process p = pb.start();
+ p.waitFor(10, TimeUnit.SECONDS);
+ String out;
+ try (InputStream is = p.getInputStream()) {
+ out = new String(is.readAllBytes());
+ }
+ String err;
+ try (InputStream is = p.getErrorStream()) {
+ err = new String(is.readAllBytes());
+ }
+ return new Result(cmd, p.exitValue(), out, err);
+ }
+
+ void checkResult(Result r) throws Exception {
+ System.out.println(r.cmd);
+ System.out.println(r.out);
+ if (r.rc != 0) {
+ System.out.println(r.err);
+ throw new Exception("rc=" + r.rc);
+ }
+ System.out.println();
+ }
+
+ void checkResult(Result r, boolean checkrc, String... lines) throws Exception {
+ System.out.println(r.cmd);
+ System.out.println(r.out);
+ if (checkrc && r.rc != 0) {
+ System.out.println(r.err);
+ throw new Exception("rc=" + r.rc);
+ }
+ String[] out = r.out.split("\r?\n");
+ Assert.assertEquals(out.length, lines.length);
+ int n = 0;
+ for (String line : lines) {
+ Assert.assertTrue(out[n++].contains(line), "\"" + line + "\"");
+ }
+ System.out.println();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/10/test/Version.java b/langtools/test/tools/jdeps/mrjar/10/test/Version.java
new file mode 100644
index 00000000000..4d27269283b
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/10/test/Version.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 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 test;
+
+public class Version {
+ public int getVersion() {
+ NonPublic np = new NonPublic();
+ String ignore = np.toString();
+ return 10;
+ }
+
+ private String getStringVersion() {
+ return "10";
+ }
+
+ private void foo() {
+ if (getStringVersion() == null) throw new NullPointerException();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/9/test/NonPublic.java b/langtools/test/tools/jdeps/mrjar/9/test/NonPublic.java
new file mode 100644
index 00000000000..112a97044a0
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/9/test/NonPublic.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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 test;
+
+class NonPublic {
+ public String toString() {
+ return "NonPublic";
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/9/test/Version.java b/langtools/test/tools/jdeps/mrjar/9/test/Version.java
new file mode 100644
index 00000000000..c4f310e35c4
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/9/test/Version.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, 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 test;
+
+public class Version {
+ public int getVersion() {
+ NonPublic np = new NonPublic();
+ String ignore = np.toString();
+ return 9;
+ }
+
+ private void foo() {
+ if (getVersion() != 9) throw new RuntimeException();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/base/p/Foo.java b/langtools/test/tools/jdeps/mrjar/base/p/Foo.java
new file mode 100644
index 00000000000..6169cb05de0
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/base/p/Foo.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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 p;
+
+// dependencies: Object
+public class Foo {
+}
diff --git a/langtools/test/tools/jdeps/mrjar/base/test/Version.java b/langtools/test/tools/jdeps/mrjar/base/test/Version.java
new file mode 100644
index 00000000000..b3c6bc9f9e0
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/base/test/Version.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, 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 test;
+
+public class Version {
+ public int getVersion() {
+ return 8;
+ }
+
+ private void foo() {
+ if (getVersion() != 8) throw new IllegalStateException();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/test/Main.java b/langtools/test/tools/jdeps/mrjar/test/Main.java
new file mode 100644
index 00000000000..994ecbf7699
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/test/Main.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, 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 test;
+
+public class Main {
+ public void run() {
+ Version v = new Version();
+ v.getVersion();
+ }
+
+ public static void main(String[] args) {
+ (new Main()).run();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/v10/q/Bar.java b/langtools/test/tools/jdeps/mrjar/v10/q/Bar.java
new file mode 100644
index 00000000000..e1b39c5b605
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/v10/q/Bar.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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 q;
+
+// dependencies: Object, q.Gee
+class Bar {
+ Gee gee = new Gee();
+}
diff --git a/langtools/test/tools/jdeps/mrjar/v10/q/Gee.java b/langtools/test/tools/jdeps/mrjar/v10/q/Gee.java
new file mode 100644
index 00000000000..c5bd2a7fa69
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/v10/q/Gee.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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 q;
+
+// dependencies: Object
+class Gee {
+}
diff --git a/langtools/test/tools/jdeps/mrjar/v9/p/Foo.java b/langtools/test/tools/jdeps/mrjar/v9/p/Foo.java
new file mode 100644
index 00000000000..e3b6dbd8f0d
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/v9/p/Foo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 p;
+
+// dependencies: Object, q.Bar
+public class Foo {
+ void crash() {
+ throw new RuntimeException();
+ }
+}
diff --git a/langtools/test/tools/jdeps/mrjar/v9/q/Bar.java b/langtools/test/tools/jdeps/mrjar/v9/q/Bar.java
new file mode 100644
index 00000000000..501e29bbfb7
--- /dev/null
+++ b/langtools/test/tools/jdeps/mrjar/v9/q/Bar.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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 q;
+
+// dependecies: Object
+class Bar {
+}
From e179ac0384f2297f20a7f44b1a0898a54a636c60 Mon Sep 17 00:00:00 2001
From: Srikanth Adayapalam
Date: Tue, 27 Sep 2016 04:34:09 +0530
Subject: [PATCH 093/114] 8164519: Rendering of supertype_target for annotated
extends clause
Eliminate inconsistencies in handling annotated super class.
Reviewed-by: jlahoda
---
.../javac/code/TypeAnnotationPosition.java | 4 +-
.../sun/tools/classfile/TypeAnnotation.java | 5 +-
.../classfile/AnnotatedExtendsTest.java | 65 +++++++++++++++++++
.../referenceinfos/ClassExtends.java | 18 ++---
4 files changed, 77 insertions(+), 15 deletions(-)
create mode 100644 langtools/test/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java
index 71d7aac0b05..6e4cd02e0ae 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java
@@ -789,7 +789,7 @@ public class TypeAnnotationPosition {
classExtends(final List location,
final JCLambda onLambda,
final int pos) {
- return classExtends(location, onLambda, -1, pos);
+ return classExtends(location, onLambda, 65535, pos);
}
/**
@@ -821,7 +821,7 @@ public class TypeAnnotationPosition {
* @param pos The position from the associated tree node.
*/
public static TypeAnnotationPosition classExtends(final int pos) {
- return classExtends(-1, pos);
+ return classExtends(65535, pos);
}
/**
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java
index 21473f4aeb5..5d591705d52 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java
@@ -130,10 +130,7 @@ public class TypeAnnotation {
break;
// class extends or implements clause
case CLASS_EXTENDS:
- int in = cr.readUnsignedShort();
- if (in == 0xFFFF)
- in = -1;
- position.type_index = in;
+ position.type_index = cr.readUnsignedShort();;
break;
// throws
case THROWS:
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
new file mode 100644
index 00000000000..456225f643b
--- /dev/null
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, 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 8164519
+ * @summary Verify that javac emits proper super type index (65535) for an annotated extends
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavapTask
+ * @run compile -g AnnotatedExtendsTest.java
+ * @run main AnnotatedExtendsTest
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class AnnotatedExtendsTest {
+
+ @Target(ElementType.TYPE_USE)
+ public @interface TA {
+ };
+
+ public class Inner extends @TA Object {}
+
+ public static strictfp void main(String args[]) throws Exception {
+ ToolBox tb = new ToolBox();
+ Path classPath = Paths.get(ToolBox.testClasses, "AnnotatedExtendsTest$Inner.class");
+ String javapOut = new JavapTask(tb)
+ .options("-v", "-p")
+ .classes(classPath.toString())
+ .run()
+ .getOutput(Task.OutputKind.DIRECT);
+ if (!javapOut.contains("0: #21(): CLASS_EXTENDS, type_index=65535"))
+ throw new AssertionError("Expected output missing: " + javapOut);
+ }
+}
\ No newline at end of file
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java
index 7922b499bfd..091d45c9196 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, 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,7 @@ import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
/*
* @test
- * @bug 8042451
+ * @bug 8042451 8164519
* @summary Test population of reference info for class extends clauses
* @modules jdk.jdeps/com.sun.tools.classfile
* @compile -g Driver.java ReferenceInfoUtil.java ClassExtends.java
@@ -33,21 +33,21 @@ import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
*/
public class ClassExtends {
- @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1)
+ @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = 65535)
@TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1)
public String regularClass() {
return "class %TEST_CLASS_NAME% extends @TA Object implements Cloneable, @TB Runnable {"
+ " public void run() { } }";
}
- @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = -1)
+ @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = 65535)
@TADescription(annotation = "RTBs", type = CLASS_EXTENDS, typeIndex = 1)
public String regularClassRepeatableAnnotation() {
return "class %TEST_CLASS_NAME% extends @RTA @RTA Object implements Cloneable, @RTB @RTB Runnable {"
+ " public void run() { } }";
}
- @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1,
+ @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = 65535,
genericLocation = { 3, 0 })
@TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1,
genericLocation = { 3, 1 })
@@ -55,7 +55,7 @@ public class ClassExtends {
return "class %TEST_CLASS_NAME% extends HashMap<@TA String, String> implements Cloneable, Map{ } ";
}
- @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = -1,
+ @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = 65535,
genericLocation = { 3, 0 })
@TADescription(annotation = "RTBs", type = CLASS_EXTENDS, typeIndex = 1,
genericLocation = { 3, 1 })
@@ -63,21 +63,21 @@ public class ClassExtends {
return "class %TEST_CLASS_NAME% extends HashMap<@RTA @RTA String, String> implements Cloneable, Map{ } ";
}
- @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1)
+ @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = 65535)
@TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1)
public String abstractClass() {
return "abstract class %TEST_CLASS_NAME% extends @TA Date implements Cloneable, @TB Runnable {"
+ " public void run() { } }";
}
- @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = -1)
+ @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = 65535)
@TADescription(annotation = "RTBs", type = CLASS_EXTENDS, typeIndex = 1)
public String abstractClassRepeatableAnnotation() {
return "abstract class %TEST_CLASS_NAME% extends @RTA @RTA Date implements Cloneable, @RTB @RTB Runnable {"
+ " public void run() { } }";
}
- @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = -1,
+ @TADescription(annotation = "RTAs", type = CLASS_EXTENDS, typeIndex = 65535,
genericLocation = { 3, 0 })
@TADescription(annotation = "RTBs", type = CLASS_EXTENDS, typeIndex = 1,
genericLocation = { 3, 1 })
From e168404209458f6c4990964e491715b544ff9482 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Tue, 27 Sep 2016 01:36:31 -0700
Subject: [PATCH 094/114] 8154525: java/net/ServerSocket/ThreadStop.java fails
intermittently with error while cleaning up threads after test
Reviewed-by: chegar
---
jdk/test/java/net/ServerSocket/ThreadStop.java | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/jdk/test/java/net/ServerSocket/ThreadStop.java b/jdk/test/java/net/ServerSocket/ThreadStop.java
index 2ebecbb8db8..adf19379280 100644
--- a/jdk/test/java/net/ServerSocket/ThreadStop.java
+++ b/jdk/test/java/net/ServerSocket/ThreadStop.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -68,23 +68,23 @@ public class ThreadStop {
thr.start();
// give server time to block in ServerSocket.accept()
- Thread.currentThread().sleep(2000);
+ Thread.sleep(2000);
// "stop" the thread
thr.stop();
// give thread time to stop
- Thread.currentThread().sleep(2000);
+ Thread.sleep(2000);
// it's platform specific if Thread.stop interrupts the
// thread - on Linux/Windows most likely that thread is
// still in accept() so we connect to server which causes
// it to unblock and do JNI-stuff with a pending exception
- try {
- Socket s = new Socket("localhost", svr.localPort());
- } catch (IOException ioe) { }
-
+ try (Socket s = new Socket("localhost", svr.localPort())) {
+ } catch (IOException ioe) {
+ }
+ thr.join();
}
}
From 0c8a532f7a561387235aea93f11302d294f8e0da Mon Sep 17 00:00:00 2001
From: Rob McKenna
Date: Tue, 27 Sep 2016 12:07:33 +0100
Subject: [PATCH 095/114] 8166747: Add invalid network / computer name cases to
isReachable known failure switch
Reviewed-by: chegar, msheppar
---
jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
index debc50a1543..3a9e650a5f8 100644
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
@@ -499,6 +499,8 @@ ping4(JNIEnv *env,
case ERROR_REQUEST_ABORTED:
case ERROR_INCORRECT_ADDRESS:
case ERROR_HOST_DOWN:
+ case ERROR_INVALID_COMPUTERNAME:
+ case ERROR_INVALID_NETNAME:
case WSAEHOSTUNREACH: /* Host Unreachable */
case WSAENETUNREACH: /* Network Unreachable */
case WSAENETDOWN: /* Network is down */
From 439cb413d5c187594e4c16a3e7559a6408bbd54f Mon Sep 17 00:00:00 2001
From: Erik Joelsson
Date: Tue, 27 Sep 2016 15:33:34 +0200
Subject: [PATCH 096/114] 8164301: jib should provide a JDK for running jtreg
with
Reviewed-by: tbell
---
common/conf/jib-profiles.js | 49 ++++++++++++++++++++++---------------
make/MainSupport.gmk | 2 ++
2 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js
index e57bbf7e4bd..d003e1815e4 100644
--- a/common/conf/jib-profiles.js
+++ b/common/conf/jib-profiles.js
@@ -224,6 +224,23 @@ var getJibProfilesCommon = function (input) {
common.configure_args_slowdebug = ["--with-debug-level=slowdebug"],
common.organization = "jpg.infra.builddeps"
+ var boot_jdk_revision = "8";
+ var boot_jdk_subdirpart = "1.8.0";
+ // JDK 8 does not work on sparc M7 cpus, need a newer update when building
+ // on such hardware.
+ if (input.build_cpu == "sparcv9") {
+ var cpu_brand = $EXEC("bash -c \"kstat -m cpu_info | grep brand | head -n1 | awk '{ print \$2 }'\"");
+ if (cpu_brand.trim() == 'SPARC-M7') {
+ boot_jdk_revision = "8u20";
+ boot_jdk_subdirpart = "1.8.0_20";
+ }
+ }
+ common.boot_jdk_revision = boot_jdk_revision;
+ common.boot_jdk_subdirpart = boot_jdk_subdirpart;
+ common.boot_jdk_home = input.get("boot_jdk", "home_path") + "/jdk"
+ + common.boot_jdk_subdirpart
+ + (input.build_os == "macosx" ? ".jdk/Contents/Home" : "");
+
return common;
};
@@ -333,8 +350,11 @@ var getJibProfilesProfiles = function (input, common) {
"run-test": {
target_os: input.build_os,
target_cpu: input.build_cpu,
- dependencies: [ "jtreg", "gnumake" ],
- labels: "test"
+ dependencies: [ "jtreg", "gnumake", "boot_jdk" ],
+ labels: "test",
+ environment: {
+ "JT_JAVA": common.boot_jdk_home
+ }
}
};
profiles = concatObjects(profiles, testOnlyProfiles);
@@ -357,18 +377,6 @@ var getJibProfilesDependencies = function (input, common) {
var boot_jdk_platform = input.build_os + "-"
+ (input.build_cpu == "x86" ? "i586" : input.build_cpu);
- var boot_jdk_revision = "8";
- var boot_jdk_subdirpart = "1.8.0";
- // JDK 8 does not work on sparc M7 cpus, need a newer update when building
- // on such hardware.
- if (input.build_cpu == "sparcv9") {
- var cpu_brand = $EXEC("bash -c \"kstat -m cpu_info | grep brand | head -n1 | awk '{ print \$2 }'\"");
- if (cpu_brand.trim() == 'SPARC-M7') {
- boot_jdk_revision = "8u20";
- boot_jdk_subdirpart = "1.8.0_20";
- }
- }
-
var devkit_platform_revisions = {
linux_x64: "gcc4.9.2-OEL6.4+1.0",
macosx_x64: "Xcode6.3-MacOSX10.9+1.0",
@@ -386,12 +394,12 @@ var getJibProfilesDependencies = function (input, common) {
boot_jdk: {
server: "javare",
module: "jdk",
- revision: boot_jdk_revision,
+ revision: common.boot_jdk_revision,
checksum_file: boot_jdk_platform + "/MD5_VALUES",
- file: boot_jdk_platform + "/jdk-" + boot_jdk_revision + "-" + boot_jdk_platform + ".tar.gz",
- configure_args: (input.build_os == "macosx"
- ? "--with-boot-jdk=" + input.get("boot_jdk", "install_path") + "/jdk" + boot_jdk_subdirpart + ".jdk/Contents/Home"
- : "--with-boot-jdk=" + input.get("boot_jdk", "install_path") + "/jdk" + boot_jdk_subdirpart)
+ file: boot_jdk_platform + "/jdk-" + common.boot_jdk_revision
+ + "-" + boot_jdk_platform + ".tar.gz",
+ configure_args: "--with-boot-jdk=" + common.boot_jdk_home,
+ environment_path: common.boot_jdk_home
},
devkit: {
@@ -420,7 +428,8 @@ var getJibProfilesDependencies = function (input, common) {
build_number: "b03",
checksum_file: "MD5_VALUES",
file: "jtreg_bin-4.2.zip",
- environment_name: "JT_HOME"
+ environment_name: "JT_HOME",
+ environment_path: input.get("jtreg", "install_path") + "/jtreg/bin"
},
gnumake: {
diff --git a/make/MainSupport.gmk b/make/MainSupport.gmk
index 7683cfeb2af..57fd68deaa5 100644
--- a/make/MainSupport.gmk
+++ b/make/MainSupport.gmk
@@ -31,11 +31,13 @@ ifndef _MAINSUPPORT_GMK
_MAINSUPPORT_GMK := 1
# Run the tests specified by $1, with PRODUCT_HOME specified by $2
+# JT_JAVA is picked up by the jtreg launcher and used to run Jtreg itself.
define RunTests
($(CD) $(SRC_ROOT)/test && $(MAKE) $(MAKE_ARGS) -j1 -k MAKEFLAGS= \
JT_HOME=$(JT_HOME) PRODUCT_HOME=$(strip $2) \
TEST_IMAGE_DIR=$(TEST_IMAGE_DIR) \
ALT_OUTPUTDIR=$(OUTPUT_ROOT) TEST_JOBS=$(TEST_JOBS) \
+ JT_JAVA=$(BOOT_JDK) \
JOBS=$(JOBS) $1) || true
endef
From 5db49c3eb293c9e0d400bb7aa3bcfe9f98e83435 Mon Sep 17 00:00:00 2001
From: Artem Smotrakov
Date: Tue, 27 Sep 2016 11:34:45 -0700
Subject: [PATCH 097/114] 8164591:
sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java failed with
SSLHandshakeException
Reviewed-by: xuelei
---
jdk/test/javax/net/ssl/templates/SSLTest.java | 493 ++++++++++++++++++
.../https/HttpsClient/ServerIdentityTest.java | 279 ++--------
2 files changed, 548 insertions(+), 224 deletions(-)
create mode 100644 jdk/test/javax/net/ssl/templates/SSLTest.java
diff --git a/jdk/test/javax/net/ssl/templates/SSLTest.java b/jdk/test/javax/net/ssl/templates/SSLTest.java
new file mode 100644
index 00000000000..48196fda86e
--- /dev/null
+++ b/jdk/test/javax/net/ssl/templates/SSLTest.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2016, 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.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.SocketTimeoutException;
+import java.security.KeyStore;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * Helper class for JSSE tests.
+ *
+ * Please run in othervm mode. SunJSSE does not support dynamic system
+ * properties, no way to re-use system properties in samevm/agentvm mode.
+ */
+public class SSLTest {
+
+ public static final String TEST_SRC = System.getProperty("test.src", ".");
+
+ /*
+ * Where do we find the keystores?
+ */
+ public static final String PATH_TO_STORES = "../etc";
+ public static final String KEY_STORE_FILE = "keystore";
+ public static final String TRUST_STORE_FILE = "truststore";
+ public static final String PASSWORD = "passphrase";
+
+ public static final int FREE_PORT = 0;
+
+ // in seconds
+ public static final long CLIENT_SIGNAL_TIMEOUT = 30L;
+ public static final long SERVER_SIGNAL_TIMEOUT = 90L;
+
+ // in millis
+ public static final int CLIENT_TIMEOUT = 15000;
+ public static final int SERVER_TIMEOUT = 30000;
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ private boolean separateServerThread = false;
+
+ /*
+ * What's the server port? Use any free port by default
+ */
+ private volatile int serverPort;
+
+ private volatile Exception serverException;
+ private volatile Exception clientException;
+
+ private Thread clientThread;
+ private Thread serverThread;
+
+ private Peer serverPeer;
+ private Peer clientPeer;
+
+ private Application serverApplication;
+ private Application clientApplication;
+
+ private SSLContext context;
+
+ /*
+ * Is the server ready to serve?
+ */
+ private final CountDownLatch serverCondition = new CountDownLatch(1);
+
+ /*
+ * Is the client ready to handshake?
+ */
+ private final CountDownLatch clientCondition = new CountDownLatch(1);
+
+ /*
+ * Public API.
+ */
+
+ public static interface Peer {
+ void run(SSLTest test) throws Exception;
+ }
+
+ public static interface Application {
+ void run(SSLSocket socket, SSLTest test) throws Exception;
+ }
+
+ public static void debug() {
+ debug("ssl");
+ }
+
+ public static void debug(String mode) {
+ System.setProperty("javax.net.debug", mode);
+ }
+
+ public static void setup(String keyFilename, String trustFilename,
+ String password) {
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", password);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", password);
+ }
+
+ public static void setup() throws Exception {
+ String keyFilename = TEST_SRC + "/" + PATH_TO_STORES + "/"
+ + KEY_STORE_FILE;
+ String trustFilename = TEST_SRC + "/" + PATH_TO_STORES + "/"
+ + TRUST_STORE_FILE;
+
+ setup(keyFilename, trustFilename, PASSWORD);
+ }
+
+ public static void print(String message, Throwable... errors) {
+ synchronized (System.out) {
+ System.out.println(message);
+ Arrays.stream(errors).forEach(e -> e.printStackTrace(System.out));
+ }
+ }
+
+ public static KeyStore loadJksKeyStore(String filename, String password)
+ throws Exception {
+
+ return loadKeyStore(filename, password, "JKS");
+ }
+
+ public static KeyStore loadKeyStore(String filename, String password,
+ String type) throws Exception {
+
+ KeyStore keystore = KeyStore.getInstance(type);
+ try (FileInputStream fis = new FileInputStream(filename)) {
+ keystore.load(fis, password.toCharArray());
+ }
+ return keystore;
+ }
+
+ public SSLTest setSeparateServerThread(boolean separateServerThread) {
+ this.separateServerThread = separateServerThread;
+ return this;
+ }
+
+ public SSLTest setServerPort(int serverPort) {
+ this.serverPort = serverPort;
+ return this;
+ }
+
+ public int getServerPort() {
+ return serverPort;
+ }
+
+ public SSLTest setSSLContext(SSLContext context) {
+ this.context = context;
+ return this;
+ }
+
+ public SSLContext getSSLContext() {
+ return context;
+ }
+
+ public SSLServerSocketFactory getSSLServerSocketFactory() {
+ if (context != null) {
+ return context.getServerSocketFactory();
+ }
+
+ return (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ }
+
+ public SSLSocketFactory getSSLSocketFactory() {
+ if (context != null) {
+ return context.getSocketFactory();
+ }
+
+ return (SSLSocketFactory) SSLSocketFactory.getDefault();
+ }
+
+ public void signalServerReady() {
+ serverCondition.countDown();
+ }
+
+ public boolean waitForClientSignal(long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ return clientCondition.await(timeout, unit);
+ }
+
+ public boolean waitForClientSignal() throws InterruptedException {
+ return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
+ }
+
+ public void signalClientReady() {
+ clientCondition.countDown();
+ }
+
+ public boolean waitForServerSignal(long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ return serverCondition.await(timeout, unit);
+ }
+
+ public boolean waitForServerSignal() throws InterruptedException {
+ return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
+ }
+
+ public SSLTest setServerPeer(Peer serverPeer) {
+ this.serverPeer = serverPeer;
+ return this;
+ }
+
+ public Peer getServerPeer() {
+ return serverPeer;
+ }
+
+ public SSLTest setServerApplication(Application serverApplication) {
+ this.serverApplication = serverApplication;
+ return this;
+ }
+
+ public Application getServerApplication() {
+ return serverApplication;
+ }
+
+ public SSLTest setClientPeer(Peer clientPeer) {
+ this.clientPeer = clientPeer;
+ return this;
+ }
+
+ public Peer getClientPeer() {
+ return clientPeer;
+ }
+
+ public SSLTest setClientApplication(Application clientApplication) {
+ this.clientApplication = clientApplication;
+ return this;
+ }
+
+ public Application getClientApplication() {
+ return clientApplication;
+ }
+
+ public void runTest() throws Exception {
+ if (separateServerThread) {
+ startServer(true, this);
+ startClient(false, this);
+ serverThread.join();
+ } else {
+ startClient(true, this);
+ startServer(false, this);
+ clientThread.join();
+ }
+
+ if (clientException != null || serverException != null) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ public SSLTest() {
+ serverPeer = (test) -> doServerSide(test);
+ clientPeer = (test) -> doClientSide(test);
+ serverApplication = (socket, test) -> runServerApplication(socket);
+ clientApplication = (socket, test) -> runClientApplication(socket);
+ }
+
+ /*
+ * Private part.
+ */
+
+
+ /*
+ * Define the server side of the test.
+ */
+ private static void doServerSide(SSLTest test) throws Exception {
+ SSLServerSocket sslServerSocket;
+
+ // kick start the server side service
+ SSLServerSocketFactory sslssf = test.getSSLServerSocketFactory();
+ sslServerSocket = (SSLServerSocket)sslssf.createServerSocket(FREE_PORT);
+
+ test.setServerPort(sslServerSocket.getLocalPort());
+ print("Server is listening on port " + test.getServerPort());
+
+ // Signal the client, the server is ready to accept connection.
+ test.signalServerReady();
+
+ // Try to accept a connection in 30 seconds.
+ SSLSocket sslSocket;
+ try {
+ sslServerSocket.setSoTimeout(SERVER_TIMEOUT);
+ sslSocket = (SSLSocket) sslServerSocket.accept();
+ print("Server accepted connection");
+ } catch (SocketTimeoutException ste) {
+ sslServerSocket.close();
+
+ // Ignore the test case if no connection within 30 seconds.
+ print("No incoming client connection in 30 seconds. "
+ + "Ignore in server side.", ste);
+ return;
+ }
+
+ // handle the connection
+ try {
+ // Is it the expected client connection?
+ //
+ // Naughty test cases or third party routines may try to
+ // connection to this server port unintentionally. In
+ // order to mitigate the impact of unexpected client
+ // connections and avoid intermittent failure, it should
+ // be checked that the accepted connection is really linked
+ // to the expected client.
+ boolean clientIsReady = test.waitForClientSignal();
+
+ if (clientIsReady) {
+ // Run the application in server side.
+ print("Run server application");
+ test.getServerApplication().run(sslSocket, test);
+ } else { // Otherwise, ignore
+ // We don't actually care about plain socket connections
+ // for TLS communication testing generally. Just ignore
+ // the test if the accepted connection is not linked to
+ // the expected client or the client connection timeout
+ // in 30 seconds.
+ print("The client is not the expected one or timeout. "
+ + "Ignore in server side.");
+ }
+ } finally {
+ sslSocket.close();
+ sslServerSocket.close();
+ }
+ }
+
+ /*
+ * Define the server side application of the test for the specified socket.
+ */
+ private static void runServerApplication(SSLSocket socket)
+ throws Exception {
+
+ // here comes the test logic
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ /*
+ * Define the client side of the test.
+ */
+ private static void doClientSide(SSLTest test) throws Exception {
+
+ // Wait for server to get started.
+ //
+ // The server side takes care of the issue if the server cannot
+ // get started in 90 seconds. The client side would just ignore
+ // the test case if the serer is not ready.
+ boolean serverIsReady = test.waitForServerSignal();
+ if (!serverIsReady) {
+ print("The server is not ready yet in 90 seconds. "
+ + "Ignore in client side.");
+ return;
+ }
+
+ SSLSocketFactory sslsf = test.getSSLSocketFactory();
+ try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
+ try {
+ sslSocket.connect(
+ new InetSocketAddress("localhost",
+ test.getServerPort()), CLIENT_TIMEOUT);
+ print("Client connected to server");
+ } catch (IOException ioe) {
+ // The server side may be impacted by naughty test cases or
+ // third party routines, and cannot accept connections.
+ //
+ // Just ignore the test if the connection cannot be
+ // established.
+ print("Cannot make a connection in 15 seconds. "
+ + "Ignore in client side.", ioe);
+ return;
+ }
+
+ // OK, here the client and server get connected.
+
+ // Signal the server, the client is ready to communicate.
+ test.signalClientReady();
+
+ // There is still a chance in theory that the server thread may
+ // wait client-ready timeout and then quit. The chance should
+ // be really rare so we don't consider it until it becomes a
+ // real problem.
+
+ // Run the application in client side.
+ print("Run client application");
+ test.getClientApplication().run(sslSocket, test);
+ }
+ }
+
+ /*
+ * Define the client side application of the test for the specified socket.
+ */
+ private static void runClientApplication(SSLSocket socket)
+ throws Exception {
+
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ }
+
+ private void startServer(boolean newThread, SSLTest test) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ serverPeer.run(test);
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ print("Server died ...", e);
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ try {
+ serverPeer.run(test);
+ } catch (Exception e) {
+ print("Server failed ...", e);
+ serverException = e;
+ }
+ }
+ }
+
+ private void startClient(boolean newThread, SSLTest test) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ clientPeer.run(test);
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ print("Client died ...", e);
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ clientPeer.run(test);
+ } catch (Exception e) {
+ print("Client failed ...", e);
+ clientException = e;
+ }
+ }
+ }
+}
diff --git a/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
index b025171d80d..8543f9dd904 100644
--- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,9 @@
* @bug 4328195
* @summary Need to include the alternate subject DN for certs,
* https should check for this
- * @run main/othervm ServerIdentityTest
+ * @library /javax/net/ssl/templates
+ * @run main/othervm ServerIdentityTest dnsstore
+ * @run main/othervm ServerIdentityTest ipstore
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
@@ -34,242 +36,71 @@
* @author Yingxian Wang
*/
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.*;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
import java.security.KeyStore;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
public class ServerIdentityTest {
- /*
- * =============================================================
- * Set the various variables needed for the tests, then
- * specify what tests to run on each side.
- */
-
- /*
- * Should we run the client or server in a separate thread?
- * Both sides can throw exceptions, but do you have a preference
- * as to which side should be the main thread.
- */
- static boolean separateServerThread = true;
-
- /*
- * Where do we find the keystores?
- */
- static String pathToStores = "./";
- static String[] keyStoreFiles = {"dnsstore", "ipstore"};
- static String[] trustStoreFiles = {"dnsstore", "ipstore"};
- static String passwd = "changeit";
-
- /*
- * Is the server ready to serve?
- */
- boolean serverReady = false;
-
- /*
- * Turn on SSL debugging?
- */
- static boolean debug = false;
-
- /*
- * If the client or server is doing some kind of object creation
- * that the other side depends on, and that thread prematurely
- * exits, you may experience a hang. The test harness will
- * terminate all hung threads after its timeout has expired,
- * currently 3 minutes by default, but you might try to be
- * smart about it....
- */
-
- /*
- * Define the server side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doServerSide() throws Exception {
- SSLServerSocketFactory sslssf =
- context.getServerSocketFactory();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket) sslssf.createServerSocket(serverPort);
- serverPort = sslServerSocket.getLocalPort();
-
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
-
- SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
- OutputStream sslOS = sslSocket.getOutputStream();
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sslOS));
- bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
- bw.flush();
- Thread.sleep(2000);
- sslSocket.getSession().invalidate();
- sslSocket.close();
- }
-
- /*
- * Define the client side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doClientSide() throws Exception {
- /*
- * Wait for server to get started.
- */
- while (!serverReady) {
- Thread.sleep(50);
- }
- String host = iphost? "127.0.0.1": "localhost";
- URL url = new URL("https://"+host+":"+serverPort+"/index.html");
-
- HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
- InputStream is = urlc.getInputStream();
- is.close();
- }
-
- /*
- * =============================================================
- * The remainder is just support stuff
- */
-
- volatile int serverPort = 0;
-
- volatile Exception serverException = null;
- volatile Exception clientException = null;
+ private static final String PASSWORD = "changeit";
public static void main(String[] args) throws Exception {
- SSLSocketFactory reservedSFactory =
- HttpsURLConnection.getDefaultSSLSocketFactory();
- try {
- for (int i = 0; i < keyStoreFiles.length; i++) {
- String keyFilename =
- System.getProperty("test.src", ".") + "/" + pathToStores +
- "/" + keyStoreFiles[i];
- String trustFilename =
- System.getProperty("test.src", ".") + "/" + pathToStores +
- "/" + trustStoreFiles[i];
+ final String keystore = args[0];
+ String keystoreFilename = SSLTest.TEST_SRC + "/" + keystore;
- System.setProperty("javax.net.ssl.keyStore", keyFilename);
- System.setProperty("javax.net.ssl.keyStorePassword", passwd);
- System.setProperty("javax.net.ssl.trustStore", trustFilename);
- System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+ SSLTest.setup(keystoreFilename, keystoreFilename, PASSWORD);
- if (debug)
- System.setProperty("javax.net.debug", "all");
- SSLContext context = SSLContext.getInstance("SSL");
+ SSLContext context = SSLContext.getInstance("SSL");
- KeyManager[] kms = new KeyManager[1];
- KeyStore ks = KeyStore.getInstance("JKS");
- FileInputStream fis = new FileInputStream(keyFilename);
- ks.load(fis, passwd.toCharArray());
- fis.close();
- KeyManager km = new MyKeyManager(ks, passwd.toCharArray());
- kms[0] = km;
- context.init(kms, null, null);
- HttpsURLConnection.setDefaultSSLSocketFactory(
- context.getSocketFactory());
-
- /*
- * Start the tests.
- */
- System.out.println("Testing " + keyFilename);
- new ServerIdentityTest(context, keyStoreFiles[i]);
- }
- } finally {
- HttpsURLConnection.setDefaultSSLSocketFactory(reservedSFactory);
- }
- }
-
- Thread clientThread = null;
- Thread serverThread = null;
-
- /*
- * Primary constructor, used to drive remainder of the test.
- *
- * Fork off the other side, then do your work.
- */
- SSLContext context;
- boolean iphost = false;
- ServerIdentityTest(SSLContext context, String keystore)
- throws Exception {
- this.context = context;
- iphost = keystore.equals("ipstore");
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
+ KeyManager[] kms = new KeyManager[1];
+ KeyStore ks = SSLTest.loadJksKeyStore(keystoreFilename, PASSWORD);
+ KeyManager km = new MyKeyManager(ks, PASSWORD.toCharArray());
+ kms[0] = km;
+ context.init(kms, null, null);
+ HttpsURLConnection.setDefaultSSLSocketFactory(
+ context.getSocketFactory());
/*
- * Wait for other side to close down.
+ * Start the test.
*/
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
+ System.out.println("Testing " + keystore);
- /*
- * When we get here, the test is pretty much over.
- *
- * If the main thread excepted, that propagates back
- * immediately. If the other thread threw an exception, we
- * should report back.
- */
- if (serverException != null)
- throw serverException;
- if (clientException != null)
- throw clientException;
- }
-
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- e.printStackTrace();
- /*
- * Our server thread just died.
- *
- * Release the client, if not active already...
- */
- System.err.println("Server died...");
- serverReady = true;
- serverException = e;
- }
+ new SSLTest()
+ .setSSLContext(context)
+ .setServerApplication((socket, test) -> {
+ BufferedWriter bw = new BufferedWriter(
+ new OutputStreamWriter(socket.getOutputStream()));
+ bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
+ bw.flush();
+ Thread.sleep(2000);
+ socket.getSession().invalidate();
+ SSLTest.print("Server application is done");
+ })
+ .setClientPeer((test) -> {
+ boolean serverIsReady = test.waitForServerSignal();
+ if (!serverIsReady) {
+ SSLTest.print(
+ "The server is not ready, ignore on client side.");
+ return;
}
- };
- serverThread.start();
- } else {
- doServerSide();
- }
- }
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died...");
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- doClientSide();
- }
+ // Signal the server, the client is ready to communicate.
+ test.signalClientReady();
+
+ String host = keystore.equals("ipstore")
+ ? "127.0.0.1" : "localhost";
+ URL url = new URL("https://" + host + ":" + test.getServerPort()
+ + "/index.html");
+
+ ((HttpURLConnection) url.openConnection())
+ .getInputStream().close();
+
+ SSLTest.print("Client is done");
+ }).runTest();
}
}
From f92bdade3df9cd032302375f168be42ff528e5b0 Mon Sep 17 00:00:00 2001
From: Hamlin Li
Date: Tue, 27 Sep 2016 18:45:51 -0700
Subject: [PATCH 098/114] 8162519: Remove ParallelPrefix.java from
ProblemList.txt
Reviewed-by: psandoz
---
jdk/test/ProblemList.txt | 2 --
1 file changed, 2 deletions(-)
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index f2e96cacf20..1381a31dc9c 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -275,8 +275,6 @@ com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-
java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java 8062512 generic-all
-java/util/Arrays/ParallelPrefix.java 8080165,8085982 generic-all
-
java/util/BitSet/BitSetStreamTest.java 8079538 generic-all
############################################################################
From 5f41b5fad79e6d0855364d51bc7787f3668ba615 Mon Sep 17 00:00:00 2001
From: Valerie Peng
Date: Wed, 28 Sep 2016 03:10:37 +0000
Subject: [PATCH 099/114] 8149802: Signature.verify() doesn't reset the
signature object on exception
Ensure the signature object is always reset after verify() is called.
Reviewed-by: xuelei
---
.../sun/security/rsa/RSASignature.java | 15 +-
.../sun/security/pkcs11/P11Signature.java | 18 ++-
.../classes/sun/security/pkcs11/Secmod.java | 8 +-
.../security/ucrypto/NativeRSASignature.java | 79 +++++-----
.../Signature/ResetAfterException.java | 140 ++++++++++++++++++
5 files changed, 213 insertions(+), 47 deletions(-)
create mode 100644 jdk/test/java/security/Signature/ResetAfterException.java
diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
index 7c707bbb15e..43e605a1457 100644
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -182,14 +182,15 @@ public abstract class RSASignature extends SignatureSpi {
}
// verify the data and return the result. See JCA doc
+ // should be reset to the state after engineInitVerify call.
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- if (sigBytes.length != RSACore.getByteLength(publicKey)) {
- throw new SignatureException("Signature length not correct: got " +
+ try {
+ if (sigBytes.length != RSACore.getByteLength(publicKey)) {
+ throw new SignatureException("Signature length not correct: got " +
sigBytes.length + " but was expecting " +
RSACore.getByteLength(publicKey));
- }
- byte[] digest = getDigestValue();
- try {
+ }
+ byte[] digest = getDigestValue();
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
byte[] unpadded = padding.unpad(decrypted);
byte[] decodedDigest = decodeSignature(digestOID, unpadded);
@@ -202,6 +203,8 @@ public abstract class RSASignature extends SignatureSpi {
return false;
} catch (IOException e) {
throw new SignatureException("Signature encoding error", e);
+ } finally {
+ resetDigest();
}
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
index 953a07bfd0b..43dfcd6a0b0 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Signature.java
@@ -616,8 +616,11 @@ final class P11Signature extends SignatureSpi {
return dsaToASN1(signature);
}
}
- } catch (PKCS11Exception e) {
- throw new ProviderException(e);
+ } catch (PKCS11Exception pe) {
+ throw new ProviderException(pe);
+ } catch (SignatureException | ProviderException e) {
+ cancelOperation();
+ throw e;
} finally {
initialized = false;
session = token.releaseSession(session);
@@ -669,8 +672,8 @@ final class P11Signature extends SignatureSpi {
}
}
return true;
- } catch (PKCS11Exception e) {
- long errorCode = e.getErrorCode();
+ } catch (PKCS11Exception pe) {
+ long errorCode = pe.getErrorCode();
if (errorCode == CKR_SIGNATURE_INVALID) {
return false;
}
@@ -682,10 +685,11 @@ final class P11Signature extends SignatureSpi {
if (errorCode == CKR_DATA_LEN_RANGE) {
return false;
}
- throw new ProviderException(e);
+ throw new ProviderException(pe);
+ } catch (SignatureException | ProviderException e) {
+ cancelOperation();
+ throw e;
} finally {
- // XXX we should not release the session if we abort above
- // before calling C_Verify
initialized = false;
session = token.releaseSession(session);
}
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
index 262bbb9afd1..2059e4bc5bf 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java
@@ -743,6 +743,7 @@ public final class Secmod {
Map trustMap = new HashMap();
Token token = provider.getToken();
Session session = null;
+ boolean exceptionOccurred = true;
try {
session = token.getOpSession();
int MAX_NUM = 8192;
@@ -762,8 +763,13 @@ public final class Secmod {
// skip put on pkcs11 error
}
}
+ exceptionOccurred = false;
} finally {
- token.releaseSession(session);
+ if (exceptionOccurred) {
+ token.killSession(session);
+ } else {
+ token.releaseSession(session);
+ }
}
return trustMap;
}
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
index ffdf51f0379..d8dd9535911 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -258,27 +258,38 @@ class NativeRSASignature extends SignatureSpi {
@Override
protected synchronized byte[] engineSign() throws SignatureException {
- byte[] sig = new byte[sigLength];
- int rv = doFinal(sig, 0, sigLength);
- if (rv < 0) {
- throw new SignatureException(new UcryptoException(-rv));
+ try {
+ byte[] sig = new byte[sigLength];
+ int rv = doFinal(sig, 0, sigLength);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sig;
+ } finally {
+ // doFinal should already be called, no need to cancel
+ reset(false);
}
- return sig;
}
@Override
protected synchronized int engineSign(byte[] outbuf, int offset, int len)
throws SignatureException {
- if (outbuf == null || (offset < 0) || (outbuf.length < (offset + sigLength))
- || (len < sigLength)) {
- throw new SignatureException("Invalid output buffer. offset: " +
- offset + ". len: " + len + ". sigLength: " + sigLength);
+ boolean doCancel = true;
+ try {
+ if (outbuf == null || (offset < 0) || (outbuf.length < (offset + sigLength))
+ || (len < sigLength)) {
+ throw new SignatureException("Invalid output buffer. offset: " +
+ offset + ". len: " + len + ". sigLength: " + sigLength);
+ }
+ int rv = doFinal(outbuf, offset, sigLength);
+ doCancel = false;
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sigLength;
+ } finally {
+ reset(doCancel);
}
- int rv = doFinal(outbuf, offset, sigLength);
- if (rv < 0) {
- throw new SignatureException(new UcryptoException(-rv));
- }
- return sigLength;
}
@Override
@@ -329,19 +340,25 @@ class NativeRSASignature extends SignatureSpi {
@Override
protected synchronized boolean engineVerify(byte[] sigBytes, int sigOfs, int sigLen)
throws SignatureException {
- if (sigBytes == null || (sigOfs < 0) || (sigBytes.length < (sigOfs + this.sigLength))
- || (sigLen != this.sigLength)) {
- throw new SignatureException("Invalid signature length: got " +
- sigLen + " but was expecting " + this.sigLength);
- }
+ boolean doCancel = true;
+ try {
+ if (sigBytes == null || (sigOfs < 0) || (sigBytes.length < (sigOfs + this.sigLength))
+ || (sigLen != this.sigLength)) {
+ throw new SignatureException("Invalid signature length: got " +
+ sigLen + " but was expecting " + this.sigLength);
+ }
- int rv = doFinal(sigBytes, sigOfs, sigLen);
- if (rv == 0) {
- return true;
- } else {
- UcryptoProvider.debug("Signature: " + mech + " verification error " +
+ int rv = doFinal(sigBytes, sigOfs, sigLen);
+ doCancel = false;
+ if (rv == 0) {
+ return true;
+ } else {
+ UcryptoProvider.debug("Signature: " + mech + " verification error " +
new UcryptoException(-rv).getMessage());
- return false;
+ return false;
+ }
+ } finally {
+ reset(doCancel);
}
}
@@ -432,13 +449,9 @@ class NativeRSASignature extends SignatureSpi {
// returns 0 (success) or negative (ucrypto error occurred)
private int doFinal(byte[] sigBytes, int sigOfs, int sigLen) {
- try {
- ensureInitialized();
- int k = nativeFinal(pCtxt.id, sign, sigBytes, sigOfs, sigLen);
- return k;
- } finally {
- reset(false);
- }
+ ensureInitialized();
+ int k = nativeFinal(pCtxt.id, sign, sigBytes, sigOfs, sigLen);
+ return k;
}
// check and return RSA key size in number of bytes
diff --git a/jdk/test/java/security/Signature/ResetAfterException.java b/jdk/test/java/security/Signature/ResetAfterException.java
new file mode 100644
index 00000000000..fe5809652e9
--- /dev/null
+++ b/jdk/test/java/security/Signature/ResetAfterException.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016, 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 8149802
+ * @summary Ensure that Signature objects are reset after verification errored out.
+ */
+import java.util.Arrays;
+import java.security.*;
+
+public class ResetAfterException {
+
+ public static void main(String[] args) throws Exception {
+
+ byte[] data = "data to be signed".getBytes();
+ byte[] shortBuffer = new byte[2];
+
+ Provider[] provs = Security.getProviders();
+ boolean failed = false;
+
+ for (Provider p : provs) {
+ Signature sig;
+ try {
+ sig = Signature.getInstance("SHA256withRSA", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ // no support, skip
+ continue;
+ }
+
+ boolean res = true;
+ System.out.println("Testing Provider: " + p.getName());
+ KeyPairGenerator keyGen = null;
+ try {
+ // It's possible that some provider, e.g. SunMSCAPI,
+ // doesn't work well with keys from other providers
+ // so we use the same provider to generate key first
+ keyGen = KeyPairGenerator.getInstance("RSA", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ keyGen = KeyPairGenerator.getInstance("RSA");
+ }
+ if (keyGen == null) {
+ throw new RuntimeException("Error: No support for RSA KeyPairGenerator");
+ }
+ keyGen.initialize(1024);
+ KeyPair keyPair = keyGen.generateKeyPair();
+
+ sig.initSign(keyPair.getPrivate());
+ sig.update(data);
+ byte[] signature = sig.sign();
+ // First check signing
+ try {
+ sig.update(data);
+ // sign with short output buffer to cause exception
+ int len = sig.sign(shortBuffer, 0, shortBuffer.length);
+ System.out.println("FAIL: Should throw SE with short buffer");
+ res = false;
+ } catch (SignatureException e) {
+ // expected exception; ignore
+ System.out.println("Expected Ex for short output buffer: " + e);
+ }
+ // Signature object should reset after a failed generation
+ sig.update(data);
+ byte[] signature2 = sig.sign();
+ if (!Arrays.equals(signature, signature2)) {
+ System.out.println("FAIL: Generated different signature");
+ res = false;
+ } else {
+ System.out.println("Generated same signature");
+ }
+
+ // Now, check signature verification
+ sig.initVerify(keyPair.getPublic());
+ sig.update(data);
+ try {
+ // first verify with valid signature bytes
+ res = sig.verify(signature);
+ } catch (SignatureException e) {
+ System.out.println("FAIL: Valid signature rejected");
+ e.printStackTrace();
+ res = false;
+ }
+
+ try {
+ sig.update(data);
+ // verify with short signaure to cause exception
+ if (sig.verify(shortBuffer)) {
+ System.out.println("FAIL: Invalid signature verified");
+ res = false;
+ } else {
+ System.out.println("Invalid signature rejected");
+ }
+ } catch (SignatureException e) {
+ // expected exception; ignore
+ System.out.println("Expected Ex for short output buffer: " + e);
+ }
+ // Signature object should reset after an a failed verification
+ sig.update(data);
+ try {
+ // verify with valid signature bytes again
+ res = sig.verify(signature);
+ if (!res) {
+ System.out.println("FAIL: Valid signature is rejected");
+ } else {
+ System.out.println("Valid signature is accepted");
+ }
+ } catch (GeneralSecurityException e) {
+ System.out.println("FAIL: Valid signature is rejected");
+ e.printStackTrace();
+ res = false;
+ }
+ failed |= !res;
+ }
+ if (failed) {
+ throw new RuntimeException("One or more test failed");
+ } else {
+ System.out.println("Test Passed");
+ }
+ }
+}
From dc417a73f74cf600e743c1e0a3f51836957cded8 Mon Sep 17 00:00:00 2001
From: Valerie Peng
Date: Wed, 28 Sep 2016 03:18:01 +0000
Subject: [PATCH 100/114] 6946830: javax.crypto.Cipher.doFinal behavior differs
depending on platform
Updated OracleUcrypto and SunPKCS11 providers with SunJCE provider behavior
Reviewed-by: xuelei
---
.../sun/security/pkcs11/P11Cipher.java | 58 +++++++++----
.../ucrypto/NativeCipherWithJavaPadding.java | 10 ++-
.../javax/crypto/Cipher/EmptyFinalBuffer.java | 85 +++++++++++++++++++
3 files changed, 133 insertions(+), 20 deletions(-)
create mode 100644 jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
index 022dc3be72a..f7eef204357 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -344,7 +344,7 @@ final class P11Cipher extends CipherSpi {
private void implInit(int opmode, Key key, byte[] iv,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- cancelOperation();
+ reset(true);
if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
throw new InvalidKeyException("Key size is invalid");
}
@@ -404,23 +404,26 @@ final class P11Cipher extends CipherSpi {
if (initialized == false) {
return;
}
- initialized = false;
+
if ((session == null) || (token.explicitCancel == false)) {
return;
}
- // cancel operation by finishing it
- int bufLen = doFinalLength(0);
- byte[] buffer = new byte[bufLen];
try {
- if (encrypt) {
- token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+ if (session.hasObjects() == false) {
+ session = token.killSession(session);
+ return;
} else {
- token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ // cancel operation by finishing it
+ int bufLen = doFinalLength(0);
+ byte[] buffer = new byte[bufLen];
+ if (encrypt) {
+ token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+ } else {
+ token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ }
}
} catch (PKCS11Exception e) {
throw new ProviderException("Cancel failed", e);
- } finally {
- reset();
}
}
@@ -483,7 +486,9 @@ final class P11Cipher extends CipherSpi {
}
// reset the states to the pre-initialized values
- private void reset() {
+ private void reset(boolean doCancel) {
+ if (doCancel) cancelOperation();
+
initialized = false;
bytesBuffered = 0;
padBufferLen = 0;
@@ -610,7 +615,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -728,7 +733,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -740,6 +745,7 @@ final class P11Cipher extends CipherSpi {
if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
int k = 0;
@@ -753,7 +759,12 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
0, out, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(), 0,
@@ -762,20 +773,24 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
System.arraycopy(padBuffer, 0, out, outOfs, k);
} else {
k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
outLen);
+ doCancel = false;
}
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
@@ -788,6 +803,7 @@ final class P11Cipher extends CipherSpi {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
@@ -818,7 +834,13 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
outAddr, outArray, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
+
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(),
@@ -828,6 +850,8 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(),
0, padBuffer, k, padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
outArray = padBuffer;
@@ -835,6 +859,7 @@ final class P11Cipher extends CipherSpi {
} else {
k = token.p11.C_DecryptFinal(session.id(),
outAddr, outArray, outOfs, outLen);
+ doCancel = false;
}
}
if ((!encrypt && paddingObj != null) ||
@@ -846,10 +871,11 @@ final class P11Cipher extends CipherSpi {
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
index 4d36710ab0d..56ddee9726b 100644
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -160,8 +160,11 @@ public class NativeCipherWithJavaPadding extends CipherSpi {
ShortBufferException {
int tbSize = (trailingBytes == null? 0:trailingBytes.position());
int dataLen = tbSize + lastData.length;
- // check total length
- if ((dataLen < 1) || (dataLen % blockSize != 0)) {
+
+ // Special handling to match SunJCE provider behavior
+ if (dataLen <= 0) {
+ return 0;
+ } else if (dataLen % blockSize != 0) {
UcryptoProvider.debug("PKCS5Padding: unpad, buffered " + tbSize +
" bytes, last block " + lastData.length + " bytes");
@@ -402,7 +405,6 @@ public class NativeCipherWithJavaPadding extends CipherSpi {
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
int estimatedOutLen = engineGetOutputSize(inLen);
-
if (out.length - outOfs < estimatedOutLen) {
throw new ShortBufferException("Actual: " + (out.length - outOfs) +
". Estimated Out Length: " + estimatedOutLen);
diff --git a/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java b/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java
new file mode 100644
index 00000000000..6479a44a8dc
--- /dev/null
+++ b/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, 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 6946830
+ * @summary Test the Cipher.doFinal() with 0-length buffer
+ * @key randomness
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class EmptyFinalBuffer {
+
+ private static final String[] ALGOS = {
+ "AES/ECB/PKCS5Padding", "AES/CBC/PKCS5Padding"
+ };
+
+ public static void main(String[] args) throws Exception {
+
+ Provider[] provs = Security.getProviders();
+
+ SecretKey key = new SecretKeySpec(new byte[16], "AES");
+
+ boolean testFailed = false;
+ for (Provider p : provs) {
+ System.out.println("Testing: " + p.getName());
+ for (String algo : ALGOS) {
+ System.out.print("Algo: " + algo);
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algo, p);
+ } catch (NoSuchAlgorithmException nsae) {
+ // skip
+ System.out.println("=> No Support");
+ continue;
+ }
+ c.init(Cipher.ENCRYPT_MODE, key);
+ AlgorithmParameters params = c.getParameters();
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ try {
+ byte[] out = c.doFinal(new byte[0]);
+ System.out.println("=> Accepted w/ " +
+ (out == null? "null" : (out.length + "-byte")) +
+ " output");
+ } catch (Exception e) {
+ testFailed = true;
+ System.out.println("=> Rejected w/ Exception");
+ e.printStackTrace();
+ }
+ }
+ }
+ if (testFailed) {
+ throw new Exception("One or more tests failed");
+ } else {
+ System.out.println("All tests passed");
+ }
+ }
+}
From cec7bce69fae370dfdf5a82966fe73d2d2cd2bce Mon Sep 17 00:00:00 2001
From: Michael Haupt
Date: Wed, 28 Sep 2016 14:02:21 +0200
Subject: [PATCH 101/114] 8151179: address issues raised by JCK team on JEP 274
API
Reviewed-by: jrose, redestad, psandoz
---
.../java/lang/invoke/MethodHandleImpl.java | 37 +-
.../java/lang/invoke/MethodHandles.java | 1581 +++++++++++------
.../classes/java/lang/invoke/MethodType.java | 22 +
.../CountedLoopIterationCountsTest.java | 2 +-
.../java/lang/invoke/JavaDocExamplesTest.java | 129 +-
.../java/lang/invoke/LoopCombinatorTest.java | 602 +++++--
6 files changed, 1669 insertions(+), 704 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index ca4f050553f..05ef3c983f0 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -1962,12 +1962,12 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* This method is bound as the predicate in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
* MethodHandle) counting loops}.
*
- * @param counter the counter parameter, passed in during loop execution.
* @param limit the upper bound of the parameter, statically bound at loop creation time.
+ * @param counter the counter parameter, passed in during loop execution.
*
* @return whether the counter has reached the limit.
*/
- static boolean countedLoopPredicate(int counter, int limit) {
+ static boolean countedLoopPredicate(int limit, int counter) {
return counter < limit;
}
@@ -1975,26 +1975,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* This method is bound as the step function in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
* MethodHandle) counting loops} to increment the counter.
*
+ * @param limit the upper bound of the loop counter (ignored).
* @param counter the loop counter.
*
* @return the loop counter incremented by 1.
*/
- static int countedLoopStep(int counter, int limit) {
+ static int countedLoopStep(int limit, int counter) {
return counter + 1;
}
- /**
- * This method is bound as a filter in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle, MethodHandle,
- * MethodHandle) counting loops} to pass the correct counter value to the body.
- *
- * @param counter the loop counter.
- *
- * @return the loop counter decremented by 1.
- */
- static int decrementCounter(int counter) {
- return counter - 1;
- }
-
/**
* This is bound to initialize the loop-local iterator in {@linkplain MethodHandles#iteratedLoop iterating loops}.
*
@@ -2164,12 +2153,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
MH_arrayIdentity = 5,
MH_countedLoopPred = 6,
MH_countedLoopStep = 7,
- MH_iteratePred = 8,
- MH_initIterator = 9,
+ MH_initIterator = 8,
+ MH_iteratePred = 9,
MH_iterateNext = 10,
- MH_decrementCounter = 11,
- MH_Array_newInstance = 12,
- MH_LIMIT = 13;
+ MH_Array_newInstance = 11,
+ MH_LIMIT = 12;
static MethodHandle getConstantHandle(int idx) {
MethodHandle handle = HANDLES[idx];
@@ -2220,18 +2208,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
case MH_countedLoopStep:
return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep",
MethodType.methodType(int.class, int.class, int.class));
- case MH_iteratePred:
- return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
- MethodType.methodType(boolean.class, Iterator.class));
case MH_initIterator:
return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator",
MethodType.methodType(Iterator.class, Iterable.class));
+ case MH_iteratePred:
+ return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
+ MethodType.methodType(boolean.class, Iterator.class));
case MH_iterateNext:
return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext",
MethodType.methodType(Object.class, Iterator.class));
- case MH_decrementCounter:
- return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter",
- MethodType.methodType(int.class, int.class));
case MH_Array_newInstance:
return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
MethodType.methodType(Object.class, Class.class, int.class));
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 28364e53ae9..104aa220932 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -44,8 +44,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ReflectPermission;
import java.nio.ByteOrder;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@@ -3114,7 +3112,7 @@ assert((int)twice.invokeExact(21) == 42);
* @see MethodHandles#explicitCastArguments
* @since 9
*/
- public static MethodHandle zero(Class> type) {
+ public static MethodHandle zero(Class> type) {
Objects.requireNonNull(type);
return type.isPrimitive() ? zero(Wrapper.forPrimitiveType(type), type) : zero(Wrapper.OBJECT, type);
}
@@ -3403,7 +3401,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
throw newIllegalArgumentException("illegal pos", pos, newTypes);
}
addTypes = addTypes.subList(pos, add);
- add -= pos; assert(addTypes.size() == add);
+ add -= pos;
+ assert(addTypes.size() == add);
}
// Do not add types which already match the existing arguments.
if (match > add || !oldTypes.equals(addTypes.subList(0, match))) {
@@ -3413,7 +3412,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
throw newIllegalArgumentException("argument lists do not match", oldTypes, newTypes);
}
addTypes = addTypes.subList(match, add);
- add -= match; assert(addTypes.size() == add);
+ add -= match;
+ assert(addTypes.size() == add);
// newTypes: ( P*[pos], M*[match], A*[add] )
// target: ( S*[skip], M*[match] )
MethodHandle adapter = target;
@@ -3423,26 +3423,37 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
// adapter: (S*[skip], M*[match], A*[add] )
if (pos > 0) {
adapter = dropArguments0(adapter, skip, newTypes.subList(0, pos));
- }
+ }
// adapter: (S*[skip], P*[pos], M*[match], A*[add] )
return adapter;
}
/**
- * Adapts a target method handle to match the given parameter type list, if necessary, by adding dummy arguments.
- * Some leading parameters are first skipped; they will be left unchanged and are otherwise ignored.
- * The remaining types in the target's parameter type list must be contained as a sub-list of the given type list,
- * at the given position.
- * Any non-matching parameter types (before or after the matching sub-list) are inserted in corresponding
- * positions of the target method handle's parameters, as if by {@link #dropArguments}.
- * (More precisely, elements in the new list before {@code pos} are inserted into the target list at {@code skip},
- * while elements in the new list after the match beginning at {@code pos} are inserted at the end of the
- * target list.)
- * The target's return type will be unchanged.
+ * Adapts a target method handle to match the given parameter type list. If necessary, adds dummy arguments. Some
+ * leading parameters can be skipped before matching begins. The remaining types in the {@code target}'s parameter
+ * type list must be a sub-list of the {@code newTypes} type list at the starting position {@code pos}. The
+ * resulting handle will have the target handle's parameter type list, with any non-matching parameter types (before
+ * or after the matching sub-list) inserted in corresponding positions of the target's original parameters, as if by
+ * {@link #dropArguments(MethodHandle, int, Class[])}.
+ *
+ * The resulting handle will have the same return type as the target handle.
+ *
+ * In more formal terms, assume these two type lists:
+ * - The target handle has the parameter type list {@code S..., M...}, with as many types in {@code S} as
+ * indicated by {@code skip}. The {@code M} types are those that are supposed to match part of the given type list,
+ * {@code newTypes}.
+ *
- The {@code newTypes} list contains types {@code P..., M..., A...}, with as many types in {@code P} as
+ * indicated by {@code pos}. The {@code M} types are precisely those that the {@code M} types in the target handle's
+ * parameter type list are supposed to match. The types in {@code A} are additional types found after the matching
+ * sub-list.
+ *
+ * Given these assumptions, the result of an invocation of {@code dropArgumentsToMatch} will have the parameter type
+ * list {@code S..., P..., M..., A...}, with the {@code P} and {@code A} types inserted as if by
+ * {@link #dropArguments(MethodHandle, int, Class[])}.
+ *
* @apiNote
- * Two method handles whose argument lists are "effectively identical" (i.e., identical
- * in a common prefix) may be mutually converted to a common type
- * by two calls to {@code dropArgumentsToMatch}, as follows:
+ * Two method handles whose argument lists are "effectively identical" (i.e., identical in a common prefix) may be
+ * mutually converted to a common type by two calls to {@code dropArgumentsToMatch}, as follows:
*
{@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
@@ -3461,14 +3472,15 @@ assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
* }
* @param target the method handle to adapt
* @param skip number of targets parameters to disregard (they will be unchanged)
- * @param newTypes the desired argument list of the method handle
+ * @param newTypes the list of types to match {@code target}'s parameter type list to
* @param pos place in {@code newTypes} where the non-skipped target parameters must occur
* @return a possibly adapted method handle
* @throws NullPointerException if either argument is null
* @throws IllegalArgumentException if any element of {@code newTypes} is {@code void.class},
* or if {@code skip} is negative or greater than the arity of the target,
* or if {@code pos} is negative or greater than the newTypes list size,
- * or if the non-skipped target parameter types match the new types at {@code pos}
+ * or if {@code newTypes} does not contain the {@code target}'s non-skipped parameter types at position
+ * {@code pos}.
* @since 9
*/
public static
@@ -3922,6 +3934,113 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
return foldArguments(target, 0, combiner);
}
+ /**
+ * Adapts a target method handle by pre-processing some of its arguments, starting at a given position, and then
+ * calling the target with the result of the pre-processing, inserted into the original sequence of arguments just
+ * before the folded arguments.
+ *
+ * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
+ * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
+ * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
+ * 0.
+ *
+ * @apiNote Example:
+ *
{@code
+ import static java.lang.invoke.MethodHandles.*;
+ import static java.lang.invoke.MethodType.*;
+ ...
+ MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+ "println", methodType(void.class, String.class))
+ .bindTo(System.out);
+ MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+ assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+ MethodHandle catTrace = foldArguments(cat, 1, trace);
+ // also prints "jum":
+ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+ * }
+ * Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the result type of the {@code target} and resulting adapter.
+ * {@code V}/{@code v} represent the type and value of the parameter and argument
+ * of {@code target} that precedes the folding position; {@code V} also is
+ * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+ * types and values of the {@code N} parameters and arguments at the folding
+ * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
+ * and values of the {@code target} parameters and arguments that precede and
+ * follow the folded parameters and arguments starting at {@code pos},
+ * respectively.
+ *
{@code
+ * // there are N arguments in A...
+ * T target(Z..., V, A[N]..., B...);
+ * V combiner(A...);
+ * T adapter(Z... z, A... a, B... b) {
+ * V v = combiner(a...);
+ * return target(z..., v, a..., b...);
+ * }
+ * // and if the combiner has a void return:
+ * T target2(Z..., A[N]..., B...);
+ * void combiner2(A...);
+ * T adapter2(Z... z, A... a, B... b) {
+ * combiner2(a...);
+ * return target2(z..., a..., b...);
+ * }
+ * }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
+ *
+ * @param target the method handle to invoke after arguments are combined
+ * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code
+ * 0}, the effect is the same as for {@link #foldArguments(MethodHandle, MethodHandle)}.
+ * @param combiner method handle to call initially on the incoming arguments
+ * @return method handle which incorporates the specified argument folding logic
+ * @throws NullPointerException if either argument is null
+ * @throws IllegalArgumentException if either of the following two conditions holds:
+ * (1) {@code combiner}'s return type is non-{@code void} and not the same as the argument type at position
+ * {@code pos} of the target signature;
+ * (2) the {@code N} argument types at position {@code pos} of the target signature (skipping one matching
+ * the {@code combiner}'s return type) are not identical with the argument types of {@code combiner}.
+ *
+ * @see #foldArguments(MethodHandle, MethodHandle)
+ * @since 9
+ */
+ public static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) {
+ MethodType targetType = target.type();
+ MethodType combinerType = combiner.type();
+ Class> rtype = foldArgumentChecks(pos, targetType, combinerType);
+ BoundMethodHandle result = target.rebind();
+ boolean dropResult = rtype == void.class;
+ LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType());
+ MethodType newType = targetType;
+ if (!dropResult) {
+ newType = newType.dropParameterTypes(pos, pos + 1);
+ }
+ result = result.copyWithExtendL(newType, lform, combiner);
+ return result;
+ }
+
+ /**
+ * As {@see foldArguments(MethodHandle, int, MethodHandle)}, but with the
+ * added capability of selecting the arguments from the targets parameters
+ * to call the combiner with. This allows us to avoid some simple cases of
+ * permutations and padding the combiner with dropArguments to select the
+ * right argument, which may ultimately produce fewer intermediaries.
+ */
+ static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner, int ... argPositions) {
+ MethodType targetType = target.type();
+ MethodType combinerType = combiner.type();
+ Class> rtype = foldArgumentChecks(pos, targetType, combinerType, argPositions);
+ BoundMethodHandle result = target.rebind();
+ boolean dropResult = rtype == void.class;
+ LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType(), argPositions);
+ MethodType newType = targetType;
+ if (!dropResult) {
+ newType = newType.dropParameterTypes(pos, pos + 1);
+ }
+ result = result.copyWithExtendL(newType, lform, combiner);
+ return result;
+ }
+
private static Class> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
int foldArgs = combinerType.parameterCount();
Class> rtype = combinerType.returnType();
@@ -4125,32 +4244,69 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* iteration. Upon termination of the loop due to one of the predicates, a corresponding finalizer is run and
* delivers the loop's result, which is the return value of the resulting handle.
*
- * Intuitively, every loop is formed by one or more "clauses", each specifying a local iteration value and/or a loop
+ * Intuitively, every loop is formed by one or more "clauses", each specifying a local iteration variable and/or a loop
* exit. Each iteration of the loop executes each clause in order. A clause can optionally update its iteration
* variable; it can also optionally perform a test and conditional loop exit. In order to express this logic in
- * terms of method handles, each clause will determine four actions:
- * - Before the loop executes, the initialization of an iteration variable or loop invariant local.
- *
- When a clause executes, an update step for the iteration variable.
- *
- When a clause executes, a predicate execution to test for loop exit.
- *
- If a clause causes a loop exit, a finalizer execution to compute the loop's return value.
+ * terms of method handles, each clause will specify up to four independent actions:
+ * - init: Before the loop executes, the initialization of an iteration variable {@code v} of type {@code V}.
+ *
- step: When a clause executes, an update step for the iteration variable {@code v}.
+ *
- pred: When a clause executes, a predicate execution to test for loop exit.
+ *
- fini: If a clause causes a loop exit, a finalizer execution to compute the loop's return value.
*
+ * The full sequence of all iteration variable types, in clause order, will be notated as {@code (V...)}.
+ * The values themselves will be {@code (v...)}. When we speak of "parameter lists", we will usually
+ * be referring to types, but in some contexts (describing execution) the lists will be of actual values.
*
* Some of these clause parts may be omitted according to certain rules, and useful default behavior is provided in
* this case. See below for a detailed description.
*
- * Each clause function, with the exception of clause initializers, is able to observe the entire loop state,
- * because it will be passed all current iteration variable values, as well as all incoming loop
- * parameters. Most clause functions will not need all of this information, but they will be formally connected as
- * if by {@link #dropArguments}.
+ * Parameters optional everywhere:
+ * Each clause function is allowed but not required to accept a parameter for each iteration variable {@code v}.
+ * As an exception, the init functions cannot take any {@code v} parameters,
+ * because those values are not yet computed when the init functions are executed.
+ * Any clause function may neglect to take any trailing subsequence of parameters it is entitled to take.
+ * In fact, any clause function may take no arguments at all.
*
+ * Loop parameters:
+ * A clause function may take all the iteration variable values it is entitled to, in which case
+ * it may also take more trailing parameters. Such extra values are called loop parameters,
+ * with their types and values notated as {@code (A...)} and {@code (a...)}.
+ * These become the parameters of the resulting loop handle, to be supplied whenever the loop is executed.
+ * (Since init functions do not accept iteration variables {@code v}, any parameter to an
+ * init function is automatically a loop parameter {@code a}.)
+ * As with iteration variables, clause functions are allowed but not required to accept loop parameters.
+ * These loop parameters act as loop-invariant values visible across the whole loop.
+ *
+ * Parameters visible everywhere:
+ * Each non-init clause function is permitted to observe the entire loop state, because it can be passed the full
+ * list {@code (v... a...)} of current iteration variable values and incoming loop parameters.
+ * The init functions can observe initial pre-loop state, in the form {@code (a...)}.
+ * Most clause functions will not need all of this information, but they will be formally connected to it
+ * as if by {@link #dropArguments}.
+ *
+ * More specifically, we shall use the notation {@code (V*)} to express an arbitrary prefix of a full
+ * sequence {@code (V...)} (and likewise for {@code (v*)}, {@code (A*)}, {@code (a*)}).
+ * In that notation, the general form of an init function parameter list
+ * is {@code (A*)}, and the general form of a non-init function parameter list is {@code (V*)} or {@code (V... A*)}.
+ *
+ * Checking clause structure:
* Given a set of clauses, there is a number of checks and adjustments performed to connect all the parts of the
* loop. They are spelled out in detail in the steps below. In these steps, every occurrence of the word "must"
- * corresponds to a place where {@link IllegalArgumentException} may be thrown if the required constraint is not met
- * by the inputs to the loop combinator. The term "effectively identical", applied to parameter type lists, means
- * that they must be identical, or else one list must be a proper prefix of the other.
+ * corresponds to a place where {@link IllegalArgumentException} will be thrown if the required constraint is not
+ * met by the inputs to the loop combinator.
+ *
+ * Effectively identical sequences:
+ *
+ * A parameter list {@code A} is defined to be effectively identical to another parameter list {@code B}
+ * if {@code A} and {@code B} are identical, or if {@code A} is shorter and is identical with a proper prefix of {@code B}.
+ * When speaking of an unordered set of parameter lists, we say they the set is "effectively identical"
+ * as a whole if the set contains a longest list, and all members of the set are effectively identical to
+ * that longest list.
+ * For example, any set of type sequences of the form {@code (V*)} is effectively identical,
+ * and the same is true if more sequences of the form {@code (V... A*)} are added.
*
* Step 0: Determine clause structure.
- * - The clause array (of type {@code MethodHandle[][]} must be non-{@code null} and contain at least one element.
+ *
- The clause array (of type {@code MethodHandle[][]}) must be non-{@code null} and contain at least one element.
*
- The clause array may not contain {@code null}s or sub-arrays longer than four elements.
*
- Clauses shorter than four elements are treated as if they were padded by {@code null} elements to length
* four. Padding takes place by appending elements to the array.
@@ -4158,30 +4314,35 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
*
- Each clause is treated as a four-tuple of functions, called "init", "step", "pred", and "fini".
*
*
- * Step 1A: Determine iteration variables.
- * - Examine init and step function return types, pairwise, to determine each clause's iteration variable type.
- *
- If both functions are omitted, use {@code void}; else if one is omitted, use the other's return type; else
- * use the common return type (they must be identical).
+ * Step 1A: Determine iteration variable types {@code (V...)}.
+ * - The iteration variable type for each clause is determined using the clause's init and step return types.
+ *
- If both functions are omitted, there is no iteration variable for the corresponding clause ({@code void} is
+ * used as the type to indicate that). If one of them is omitted, the other's return type defines the clause's
+ * iteration variable type. If both are given, the common return type (they must be identical) defines the clause's
+ * iteration variable type.
*
- Form the list of return types (in clause order), omitting all occurrences of {@code void}.
- *
- This list of types is called the "common prefix".
+ *
- This list of types is called the "iteration variable types" ({@code (V...)}).
*
*
- * Step 1B: Determine loop parameters.
- * - If at least one init function is given,
- * - Examine init function parameter lists.
- *
- Omitted init functions are deemed to have {@code null} parameter lists.
- *
- All init function parameter lists must be effectively identical.
- *
- The longest parameter list (which is necessarily unique) is called the "common suffix".
- *
- * - If no init function is given,
- * - Examine the suffixes of the step, pred, and fini parameter lists, after removing the "common prefix".
- *
- The longest of these suffixes is taken as the "common suffix".
- *
+ * Step 1B: Determine loop parameters {@code (A...)}.
+ * - Examine and collect init function parameter lists (which are of the form {@code (A*)}).
+ *
- Examine and collect the suffixes of the step, pred, and fini parameter lists, after removing the iteration variable types.
+ * (They must have the form {@code (V... A*)}; collect the {@code (A*)} parts only.)
+ *
- Do not collect suffixes from step, pred, and fini parameter lists that do not begin with all the iteration variable types.
+ * (These types will checked in step 2, along with all the clause function types.)
+ *
- Omitted clause functions are ignored. (Equivalently, they are deemed to have empty parameter lists.)
+ *
- All of the collected parameter lists must be effectively identical.
+ *
- The longest parameter list (which is necessarily unique) is called the "external parameter list" ({@code (A...)}).
+ *
- If there is no such parameter list, the external parameter list is taken to be the empty sequence.
+ *
- The combined list consisting of iteration variable types followed by the external parameter types is called
+ * the "internal parameter list".
+ *
*
* Step 1C: Determine loop return type.
* - Examine fini function return types, disregarding omitted fini functions.
- *
- If there are no fini functions, use {@code void} as the loop return type.
- *
- Otherwise, use the common return type of the fini functions; they must all be identical.
+ *
- If there are no fini functions, the loop return type is {@code void}.
+ *
- Otherwise, the common return type {@code R} of the fini functions (their return types must be identical) defines the loop return
+ * type.
*
*
* Step 1D: Check other types.
@@ -4190,69 +4351,107 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
*
*
* Step 2: Determine parameter lists.
- * - The parameter list for the resulting loop handle will be the "common suffix".
- *
- The parameter list for init functions will be adjusted to the "common suffix". (Note that their parameter
- * lists are already effectively identical to the common suffix.)
- *
- The parameter list for non-init (step, pred, and fini) functions will be adjusted to the common prefix
- * followed by the common suffix, called the "common parameter sequence".
- *
- Every non-init, non-omitted function parameter list must be effectively identical to the common parameter
- * sequence.
+ *
- The parameter list for the resulting loop handle will be the external parameter list {@code (A...)}.
+ *
- The parameter list for init functions will be adjusted to the external parameter list.
+ * (Note that their parameter lists are already effectively identical to this list.)
+ *
- The parameter list for every non-omitted, non-init (step, pred, and fini) function must be
+ * effectively identical to the internal parameter list {@code (V... A...)}.
*
*
* Step 3: Fill in omitted functions.
- * - If an init function is omitted, use a {@linkplain #constant constant function} of the appropriate
- * {@code null}/zero/{@code false}/{@code void} type. (For this purpose, a constant {@code void} is simply a
- * function which does nothing and returns {@code void}; it can be obtained from another constant function by
- * {@linkplain MethodHandle#asType type conversion}.)
+ *
- If an init function is omitted, use a {@linkplain #empty default value} for the clause's iteration variable
+ * type.
*
- If a step function is omitted, use an {@linkplain #identity identity function} of the clause's iteration
* variable type; insert dropped argument parameters before the identity function parameter for the non-{@code void}
* iteration variables of preceding clauses. (This will turn the loop variable into a local loop invariant.)
- *
- If a pred function is omitted, the corresponding fini function must also be omitted.
*
- If a pred function is omitted, use a constant {@code true} function. (This will keep the loop going, as far
- * as this clause is concerned.)
- *
- If a fini function is omitted, use a constant {@code null}/zero/{@code false}/{@code void} function of the
+ * as this clause is concerned. Note that in such cases the corresponding fini function is unreachable.)
+ *
- If a fini function is omitted, use a {@linkplain #empty default value} for the
* loop return type.
*
*
* Step 4: Fill in missing parameter types.
- * - At this point, every init function parameter list is effectively identical to the common suffix, but some
- * lists may be shorter. For every init function with a short parameter list, pad out the end of the list by
- * {@linkplain #dropArguments dropping arguments}.
- *
- At this point, every non-init function parameter list is effectively identical to the common parameter
- * sequence, but some lists may be shorter. For every non-init function with a short parameter list, pad out the end
- * of the list by {@linkplain #dropArguments dropping arguments}.
+ *
- At this point, every init function parameter list is effectively identical to the external parameter list {@code (A...)},
+ * but some lists may be shorter. For every init function with a short parameter list, pad out the end of the list.
+ *
- At this point, every non-init function parameter list is effectively identical to the internal parameter
+ * list {@code (V... A...)}, but some lists may be shorter. For every non-init function with a short parameter list,
+ * pad out the end of the list.
+ *
- Argument lists are padded out by {@linkplain #dropArgumentsToMatch dropping unused trailing arguments}.
*
*
* Final observations.
* - After these steps, all clauses have been adjusted by supplying omitted functions and arguments.
- *
- All init functions have a common parameter type list, which the final loop handle will also have.
- *
- All fini functions have a common return type, which the final loop handle will also have.
- *
- All non-init functions have a common parameter type list, which is the common parameter sequence, of
- * (non-{@code void}) iteration variables followed by loop parameters.
- *
- Each pair of init and step functions agrees in their return types.
- *
- Each non-init function will be able to observe the current values of all iteration variables, by means of the
- * common prefix.
+ *
- All init functions have a common parameter type list {@code (A...)}, which the final loop handle will also have.
+ *
- All fini functions have a common return type {@code R}, which the final loop handle will also have.
+ *
- All non-init functions have a common parameter type list {@code (V... A...)}, of
+ * (non-{@code void}) iteration variables {@code V} followed by loop parameters.
+ *
- Each pair of init and step functions agrees in their return type {@code V}.
+ *
- Each non-init function will be able to observe the current values {@code (v...)} of all iteration variables.
+ *
- Every function will be able to observe the incoming values {@code (a...)} of all loop parameters.
*
*
+ * Example. As a consequence of step 1A above, the {@code loop} combinator has the following property:
+ *
+ * - Given {@code N} clauses {@code Cn = {null, Sn, Pn}} with {@code n = 1..N}.
+ *
- Suppose predicate handles {@code Pn} are either {@code null} or have no parameters.
+ * (Only one {@code Pn} has to be non-{@code null}.)
+ *
- Suppose step handles {@code Sn} have signatures {@code (B1..BX)Rn}, for some constant {@code X>=N}.
+ *
- Suppose {@code Q} is the count of non-void types {@code Rn}, and {@code (V1...VQ)} is the sequence of those types.
+ *
- It must be that {@code Vn == Bn} for {@code n = 1..min(X,Q)}.
+ *
- The parameter types {@code Vn} will be interpreted as loop-local state elements {@code (V...)}.
+ *
- Any remaining types {@code BQ+1..BX} (if {@code Q
+ * In this example, the loop handle parameters {@code (A...)} were derived from the step functions,
+ * which is natural if most of the loop computation happens in the steps. For some loops,
+ * the burden of computation might be heaviest in the pred functions, and so the pred functions
+ * might need to accept the loop parameter values. For loops with complex exit logic, the fini
+ * functions might need to accept loop parameters, and likewise for loops with complex entry logic,
+ * where the init functions will need the extra parameters. For such reasons, the rules for
+ * determining these parameters are as symmetric as possible, across all clause parts.
+ * In general, the loop parameters function as common invariant values across the whole
+ * loop, while the iteration variables function as common variant values, or (if there is
+ * no step function) as internal loop invariant temporaries.
+ *
* Loop execution.
- * - When the loop is called, the loop input values are saved in locals, to be passed (as the common suffix) to
+ *
- When the loop is called, the loop input values are saved in locals, to be passed to
* every clause function. These locals are loop invariant.
- *
- Each init function is executed in clause order (passing the common suffix) and the non-{@code void} values
- * are saved (as the common prefix) into locals. These locals are loop varying (unless their steps are identity
- * functions, as noted above).
- *
- All function executions (except init functions) will be passed the common parameter sequence, consisting of
- * the non-{@code void} iteration values (in clause order) and then the loop inputs (in argument order).
+ *
- Each init function is executed in clause order (passing the external arguments {@code (a...)})
+ * and the non-{@code void} values are saved (as the iteration variables {@code (v...)}) into locals.
+ * These locals will be loop varying (unless their steps behave as identity functions, as noted above).
+ *
- All function executions (except init functions) will be passed the internal parameter list, consisting of
+ * the non-{@code void} iteration values {@code (v...)} (in clause order) and then the loop inputs {@code (a...)}
+ * (in argument order).
*
- The step and pred functions are then executed, in clause order (step before pred), until a pred function
* returns {@code false}.
- *
- The non-{@code void} result from a step function call is used to update the corresponding loop variable. The
- * updated value is immediately visible to all subsequent function calls.
+ *
- The non-{@code void} result from a step function call is used to update the corresponding value in the
+ * sequence {@code (v...)} of loop variables.
+ * The updated value is immediately visible to all subsequent function calls.
*
- If a pred function returns {@code false}, the corresponding fini function is called, and the resulting value
- * is returned from the loop as a whole.
+ * (of type {@code R}) is returned from the loop as a whole.
+ *
- If all the pred functions always return true, no fini function is ever invoked, and the loop cannot exit
+ * except by throwing an exception.
*
*
- * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the types / values
- * of loop variables; {@code A}/{@code a}, those of arguments passed to the resulting loop; and {@code R}, the
- * result types of finalizers as well as of the resulting loop.
+ * Usage tips.
+ *
+ * - Although each step function will receive the current values of all the loop variables,
+ * sometimes a step function only needs to observe the current value of its own variable.
+ * In that case, the step function may need to explicitly {@linkplain #dropArguments drop all preceding loop variables}.
+ * This will require mentioning their types, in an expression like {@code dropArguments(step, 0, V0.class, ...)}.
+ *
- Loop variables are not required to vary; they can be loop invariant. A clause can create
+ * a loop invariant by a suitable init function with no step, pred, or fini function. This may be
+ * useful to "wire" an incoming loop argument into the step or pred function of an adjacent loop variable.
+ *
- If some of the clause functions are virtual methods on an instance, the instance
+ * itself can be conveniently placed in an initial invariant loop "variable", using an initial clause
+ * like {@code new MethodHandle[]{identity(ObjType.class)}}. In that case, the instance reference
+ * will be the first iteration variable value, and it will be easy to use virtual
+ * methods as clause parts, since all of them will take a leading instance reference matching that value.
+ *
+ *
+ * Here is pseudocode for the resulting loop handle. As above, {@code V} and {@code v} represent the types
+ * and values of loop variables; {@code A} and {@code a} represent arguments passed to the whole loop;
+ * and {@code R} is the common result type of all finalizers as well as of the resulting loop.
*
{@code
* V... init...(A...);
* boolean pred...(V..., A...);
@@ -4270,6 +4469,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* }
* }
* }
+ * Note that the parameter type lists {@code (V...)} and {@code (A...)} have been expanded
+ * to their full length, even though individual clause functions may neglect to take them all.
+ * As noted above, missing parameters are filled in as if by {@link #dropArgumentsToMatch}.
*
* @apiNote Example:
*
{@code
@@ -4286,6 +4488,43 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
* assertEquals(120, loop.invoke(5));
* }
+ * The same example, dropping arguments and using combinators:
+ * {@code
+ * // simplified implementation of the factorial function as a loop handle
+ * static int inc(int i) { return i + 1; } // drop acc, k
+ * static int mult(int i, int acc) { return i * acc; } //drop k
+ * static boolean cmp(int i, int k) { return i < k; }
+ * // assume MH_inc, MH_mult, and MH_cmp are handles to the above methods
+ * // null initializer for counter, should initialize to 0
+ * MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+ * MethodHandle MH_pred = MethodHandles.dropArguments(MH_cmp, 1, int.class); // drop acc
+ * MethodHandle MH_fin = MethodHandles.dropArguments(MethodHandles.identity(int.class), 0, int.class); // drop i
+ * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+ * MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+ * MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ * assertEquals(720, loop.invoke(6));
+ * }
+ * A similar example, using a helper object to hold a loop parameter:
+ * {@code
+ * // instance-based implementation of the factorial function as a loop handle
+ * static class FacLoop {
+ * final int k;
+ * FacLoop(int k) { this.k = k; }
+ * int inc(int i) { return i + 1; }
+ * int mult(int i, int acc) { return i * acc; }
+ * boolean pred(int i) { return i < k; }
+ * int fin(int i, int acc) { return acc; }
+ * }
+ * // assume MH_FacLoop is a handle to the constructor
+ * // assume MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
+ * // null initializer for counter, should initialize to 0
+ * MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+ * MethodHandle[] instanceClause = new MethodHandle[]{MH_FacLoop};
+ * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+ * MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+ * MethodHandle loop = MethodHandles.loop(instanceClause, counterClause, accumulatorClause);
+ * assertEquals(5040, loop.invoke(7));
+ * }
*
* @param clauses an array of arrays (4-tuples) of {@link MethodHandle}s adhering to the rules described above.
*
@@ -4301,7 +4540,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
*/
public static MethodHandle loop(MethodHandle[]... clauses) {
// Step 0: determine clause structure.
- checkLoop0(clauses);
+ loopChecks0(clauses);
List init = new ArrayList<>();
List step = new ArrayList<>();
@@ -4318,7 +4557,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
assert Stream.of(init, step, pred, fini).map(List::size).distinct().count() == 1;
final int nclauses = init.size();
- // Step 1A: determine iteration variables.
+ // Step 1A: determine iteration variables (V...).
final List> iterationVariableTypes = new ArrayList<>();
for (int i = 0; i < nclauses; ++i) {
MethodHandle in = init.get(i);
@@ -4326,7 +4565,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
if (in == null && st == null) {
iterationVariableTypes.add(void.class);
} else if (in != null && st != null) {
- checkLoop1a(i, in, st);
+ loopChecks1a(i, in, st);
iterationVariableTypes.add(in.type().returnType());
} else {
iterationVariableTypes.add(in == null ? st.type().returnType() : in.type().returnType());
@@ -4335,20 +4574,20 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
final List> commonPrefix = iterationVariableTypes.stream().filter(t -> t != void.class).
collect(Collectors.toList());
- // Step 1B: determine loop parameters.
+ // Step 1B: determine loop parameters (A...).
final List> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
- checkLoop1b(init, commonSuffix);
+ loopChecks1b(init, commonSuffix);
// Step 1C: determine loop return type.
// Step 1D: check other types.
final Class> loopReturnType = fini.stream().filter(Objects::nonNull).map(MethodHandle::type).
map(MethodType::returnType).findFirst().orElse(void.class);
- checkLoop1cd(pred, fini, loopReturnType);
+ loopChecks1cd(pred, fini, loopReturnType);
// Step 2: determine parameter lists.
final List> commonParameterSequence = new ArrayList<>(commonPrefix);
commonParameterSequence.addAll(commonSuffix);
- checkLoop2(step, pred, fini, commonParameterSequence);
+ loopChecks2(step, pred, fini, commonParameterSequence);
// Step 3: fill in omitted functions.
for (int i = 0; i < nclauses; ++i) {
@@ -4382,6 +4621,79 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
return MethodHandleImpl.makeLoop(loopReturnType, commonSuffix, finit, fstep, fpred, ffini);
}
+ private static void loopChecks0(MethodHandle[][] clauses) {
+ if (clauses == null || clauses.length == 0) {
+ throw newIllegalArgumentException("null or no clauses passed");
+ }
+ if (Stream.of(clauses).anyMatch(Objects::isNull)) {
+ throw newIllegalArgumentException("null clauses are not allowed");
+ }
+ if (Stream.of(clauses).anyMatch(c -> c.length > 4)) {
+ throw newIllegalArgumentException("All loop clauses must be represented as MethodHandle arrays with at most 4 elements.");
+ }
+ }
+
+ private static void loopChecks1a(int i, MethodHandle in, MethodHandle st) {
+ if (in.type().returnType() != st.type().returnType()) {
+ throw misMatchedTypes("clause " + i + ": init and step return types", in.type().returnType(),
+ st.type().returnType());
+ }
+ }
+
+ private static List> longestParameterList(Stream mhs, int skipSize) {
+ final List> empty = List.of();
+ final List> longest = mhs.filter(Objects::nonNull).
+ // take only those that can contribute to a common suffix because they are longer than the prefix
+ map(MethodHandle::type).
+ filter(t -> t.parameterCount() > skipSize).
+ map(MethodType::parameterList).
+ reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ return longest.size() == 0 ? empty : longest.subList(skipSize, longest.size());
+ }
+
+ private static List> longestParameterList(List>> lists) {
+ final List> empty = List.of();
+ return lists.stream().reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ }
+
+ private static List> buildCommonSuffix(List init, List step, List pred, List fini, int cpSize) {
+ final List> longest1 = longestParameterList(Stream.of(step, pred, fini).flatMap(List::stream), cpSize);
+ final List> longest2 = longestParameterList(init.stream(), 0);
+ return longestParameterList(Arrays.asList(longest1, longest2));
+ }
+
+ private static void loopChecks1b(List init, List> commonSuffix) {
+ if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).
+ anyMatch(t -> !t.effectivelyIdenticalParameters(0, commonSuffix))) {
+ throw newIllegalArgumentException("found non-effectively identical init parameter type lists: " + init +
+ " (common suffix: " + commonSuffix + ")");
+ }
+ }
+
+ private static void loopChecks1cd(List pred, List fini, Class> loopReturnType) {
+ if (fini.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
+ anyMatch(t -> t != loopReturnType)) {
+ throw newIllegalArgumentException("found non-identical finalizer return types: " + fini + " (return type: " +
+ loopReturnType + ")");
+ }
+
+ if (!pred.stream().filter(Objects::nonNull).findFirst().isPresent()) {
+ throw newIllegalArgumentException("no predicate found", pred);
+ }
+ if (pred.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
+ anyMatch(t -> t != boolean.class)) {
+ throw newIllegalArgumentException("predicates must have boolean return type", pred);
+ }
+ }
+
+ private static void loopChecks2(List step, List pred, List fini, List> commonParameterSequence) {
+ if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
+ anyMatch(t -> !t.effectivelyIdenticalParameters(0, commonParameterSequence))) {
+ throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
+ "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
+ }
+ }
+
private static List fillParameterTypes(List hs, final List