From 54c613acd7a7f051e65d73a1318346cb4f5a234a Mon Sep 17 00:00:00 2001
From: Zixian Cai
Date: Tue, 24 Oct 2023 14:36:52 +0000
Subject: [PATCH 01/19] 8318693: Fix rendering for code blocks nested under
list items in building.md
Reviewed-by: erikj, ccleary
---
doc/building.html | 101 ++++++++++++++++++++++++++++------------------
doc/building.md | 21 +++++++---
2 files changed, 78 insertions(+), 44 deletions(-)
diff --git a/doc/building.html b/doc/building.html
index feb699fd24d62..2348c398a534b 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -819,11 +819,11 @@
Some command line examples:
+bash configure --with-freetype=/cygdrive/c/freetype-i586 --with-target-bits=32
Create a debug build with the server
JVM and DTrace
-enabled:
-bash configure --enable-debug --with-jvm-variants=server --enable-dtrace
+enabled:
+bash configure --enable-debug --with-jvm-variants=server --enable-dtrace
Here follows some of the most common and important
@@ -1331,14 +1331,12 @@
ALSA
libasound2-dev
packages for your target system.
Download them to /tmp.
Install the libraries into the cross-compilation toolchain. For
-instance:
-
+instance:
cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc
dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb .
-dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .
-
X11
You will need X11 libraries suitable for your target system.
@@ -1372,21 +1370,18 @@
X11
Install the libraries into the cross-compilation toolchain. For
instance:
- cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc/usr
- mkdir X11R6
- cd X11R6
- for deb in /tmp/target-x11/*.deb ; do dpkg-deb -x $deb . ; done
- mv usr/* .
- cd lib
- cp arm-linux-gnueabihf/* .
- ```
-
-You can ignore the following messages. These libraries are not needed to
-successfully complete a full JDK build.
-cp: cannot stat
-arm-linux-gnueabihf/libICE.so': No such file or directory cp: cannot stat
arm-linux-gnueabihf/libSM.so':
-No such file or directory cp: cannot stat
-`arm-linux-gnueabihf/libXt.so': No such file or directory ```
+cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc/usr
+mkdir X11R6
+cd X11R6
+for deb in /tmp/target-x11/*.deb ; do dpkg-deb -x $deb . ; done
+mv usr/* .
+cd lib
+cp arm-linux-gnueabihf/* .
+You can ignore the following messages. These libraries are not needed
+to successfully complete a full JDK build.
+cp: cannot stat `arm-linux-gnueabihf/libICE.so': No such file or directory
+cp: cannot stat `arm-linux-gnueabihf/libSM.so': No such file or directory
+cp: cannot stat `arm-linux-gnueabihf/libXt.so': No such file or directory
If the X11 libraries are not properly detected by
configure
, you can point them out by
--with-x
.
@@ -1404,17 +1399,30 @@ Cross compiling with
For example, cross-compiling to AArch64 from x86_64 could be done
like this:
-Install cross-compiler on the build system:
-apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
+Install cross-compiler on the build system:
+apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
Create chroot on the build system, configuring it for
-target system:
-sudo debootstrap \ --arch=arm64 \ --verbose \ --include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev,libffi-dev \ --resolve-deps \ buster \ ~/sysroot-arm64 \ http://httpredir.debian.org/debian/ # If the target architecture is `riscv64`, # the path should be `debian-ports` instead of `debian`.
+target system:
+
sudo debootstrap \
+ --arch=arm64 \
+ --verbose \
+ --include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev,libffi-dev \
+ --resolve-deps \
+ buster \
+ ~/sysroot-arm64 \
+ http://httpredir.debian.org/debian/
+# If the target architecture is `riscv64`,
+# the path should be `debian-ports` instead of `debian`.
Make sure the symlinks inside the newly created chroot point to
-proper locations:
-sudo chroot ~/sysroot-arm64 symlinks -cr .
+proper locations:
+sudo chroot ~/sysroot-arm64 symlinks -cr .
Configure and build with newly created chroot as
-sysroot/toolchain-path:
-sh ./configure \ --openjdk-target=aarch64-linux-gnu \ --with-sysroot=~/sysroot-arm64 make images ls build/linux-aarch64-server-release/
+sysroot/toolchain-path:
+sh ./configure \
+ --openjdk-target=aarch64-linux-gnu \
+ --with-sysroot=~/sysroot-arm64
+make images
+ls build/linux-aarch64-server-release/
The build does not create new files in that chroot, so it can be
reused for multiple builds without additional cleanup.
@@ -1566,12 +1574,27 @@ Building for RISC-V
placeholder <toolchain-installed-path>
shown below is
the path where you want to install the toolchain.
-Install the RISC-V GNU compiler toolchain:
-git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain cd riscv-gnu-toolchain ./configure --prefix=<toolchain-installed-path> make linux export PATH=<toolchain-installed-path>/bin:$PATH
-Cross-compile all the required libraries:
-# An example for libffi git clone https://github.com/libffi/libffi cd libffi ./configure --host=riscv64-unknown-linux-gnu --prefix=<toolchain-installed-path>/sysroot/usr make make install
-Configure and build OpenJDK:
-bash configure \ --with-boot-jdk=$BOOT_JDK \ --openjdk-target=riscv64-linux-gnu \ --with-sysroot=<toolchain-installed-path>/sysroot \ --with-toolchain-path=<toolchain-installed-path>/bin \ --with-extra-path=<toolchain-installed-path>/bin make images
+Install the RISC-V GNU compiler toolchain:
+git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain
+cd riscv-gnu-toolchain
+./configure --prefix=<toolchain-installed-path>
+make linux
+export PATH=<toolchain-installed-path>/bin:$PATH
+Cross-compile all the required libraries:
+# An example for libffi
+git clone https://github.com/libffi/libffi
+cd libffi
+./configure --host=riscv64-unknown-linux-gnu --prefix=<toolchain-installed-path>/sysroot/usr
+make
+make install
+Configure and build OpenJDK:
+bash configure \
+ --with-boot-jdk=$BOOT_JDK \
+ --openjdk-target=riscv64-linux-gnu \
+ --with-sysroot=<toolchain-installed-path>/sysroot \
+ --with-toolchain-path=<toolchain-installed-path>/bin \
+ --with-extra-path=<toolchain-installed-path>/bin
+make images
Building for musl
Just like it's possible to cross-compile for a different CPU, it's
diff --git a/doc/building.md b/doc/building.md
index 415454cf6c36c..ac79cb314b6bb 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -626,11 +626,13 @@ automatically, it will exit and inform you about the problem.
Some command line examples:
* Create a 32-bit build for Windows with FreeType2 in `C:\freetype-i586`:
+
```
bash configure --with-freetype=/cygdrive/c/freetype-i586 --with-target-bits=32
```
* Create a debug build with the `server` JVM and DTrace enabled:
+
```
bash configure --enable-debug --with-jvm-variants=server --enable-dtrace
```
@@ -1100,11 +1102,12 @@ Note that alsa is needed even if you only want to build a headless JDK.
system. Download them to /tmp.
* Install the libraries into the cross-compilation toolchain. For instance:
-```
-cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc
-dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb .
-dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .
-```
+
+ ```
+ cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc
+ dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb .
+ dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .
+ ```
* If alsa is not properly detected by `configure`, you can point it out by
`--with-alsa`.
@@ -1140,6 +1143,7 @@ Note that X11 is needed even if you only want to build a headless JDK.
* libxext-dev
* Install the libraries into the cross-compilation toolchain. For instance:
+
```
cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc/usr
mkdir X11R6
@@ -1173,11 +1177,13 @@ for foreign architectures with native compilation speed.
For example, cross-compiling to AArch64 from x86_64 could be done like this:
* Install cross-compiler on the *build* system:
+
```
apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
```
* Create chroot on the *build* system, configuring it for *target* system:
+
```
sudo debootstrap \
--arch=arm64 \
@@ -1192,11 +1198,13 @@ For example, cross-compiling to AArch64 from x86_64 could be done like this:
```
* Make sure the symlinks inside the newly created chroot point to proper locations:
+
```
sudo chroot ~/sysroot-arm64 symlinks -cr .
```
* Configure and build with newly created chroot as sysroot/toolchain-path:
+
```
sh ./configure \
--openjdk-target=aarch64-linux-gnu \
@@ -1255,6 +1263,7 @@ complicate the building process. The placeholder ``
shown below is the path where you want to install the toolchain.
* Install the RISC-V GNU compiler toolchain:
+
```
git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
@@ -1264,6 +1273,7 @@ shown below is the path where you want to install the toolchain.
```
* Cross-compile all the required libraries:
+
```
# An example for libffi
git clone https://github.com/libffi/libffi
@@ -1274,6 +1284,7 @@ shown below is the path where you want to install the toolchain.
```
* Configure and build OpenJDK:
+
```
bash configure \
--with-boot-jdk=$BOOT_JDK \
From e2720987b921b95fd8010cea60d2d6e436e5ebaa Mon Sep 17 00:00:00 2001
From: Vicente Romero
Date: Tue, 24 Oct 2023 14:45:10 +0000
Subject: [PATCH 02/19] 8318160: javac does not reject private method reference
with type-variable receiver
Reviewed-by: mcimadamore
---
.../com/sun/tools/javac/comp/Resolve.java | 12 +++++++
...PrivateMethodReferenceWithTypeVarTest.java | 34 +++++++++++++++++++
.../PrivateMethodReferenceWithTypeVarTest.out | 4 +++
3 files changed, 50 insertions(+)
create mode 100644 test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.java
create mode 100644 test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.out
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
index 295bb192a4288..ab84d372bd72d 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
@@ -3605,6 +3605,18 @@ ReferenceKind referenceKind(Symbol sym) {
ReferenceKind.BOUND;
}
}
+
+ @Override
+ Symbol access(Env env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+ if (originalSite.hasTag(TYPEVAR) && sym.kind == MTH) {
+ sym = (sym.flags() & Flags.PRIVATE) != 0 ?
+ new AccessError(env, site, sym) :
+ sym;
+ return accessBase(sym, pos, location, originalSite, name, true);
+ } else {
+ return super.access(env, pos, location, sym);
+ }
+ }
}
/**
diff --git a/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.java b/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.java
new file mode 100644
index 0000000000000..b87783416a383
--- /dev/null
+++ b/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.java
@@ -0,0 +1,34 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8318160
+ * @summary javac does not reject private method reference with type-variable receiver
+ * @compile/fail/ref=PrivateMethodReferenceWithTypeVarTest.out -XDrawDiagnostics PrivateMethodReferenceWithTypeVarTest.java
+ */
+
+import java.util.function.*;
+
+class PrivateMethodReferenceWithTypeVarTest {
+ class Foo {
+ X get() { return null; }
+ }
+
+ private String asString() {
+ return "bar";
+ }
+
+ private String asString2(Object o) {
+ return "bar";
+ }
+
+ static Function m1() {
+ return T::asString;
+ }
+
+ static Function m2(T t) {
+ return t::asString2;
+ }
+
+ static Function, String> m2(Foo extends PrivateMethodReferenceWithTypeVarTest> foo) {
+ return foo.get()::asString2;
+ }
+}
diff --git a/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.out b/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.out
new file mode 100644
index 0000000000000..b4dac12a9ae59
--- /dev/null
+++ b/test/langtools/tools/javac/lambda/methodReference/PrivateMethodReferenceWithTypeVarTest.out
@@ -0,0 +1,4 @@
+PrivateMethodReferenceWithTypeVarTest.java:24:16: compiler.err.report.access: asString(), private, PrivateMethodReferenceWithTypeVarTest
+PrivateMethodReferenceWithTypeVarTest.java:28:16: compiler.err.report.access: asString2(java.lang.Object), private, PrivateMethodReferenceWithTypeVarTest
+PrivateMethodReferenceWithTypeVarTest.java:32:16: compiler.err.report.access: asString2(java.lang.Object), private, PrivateMethodReferenceWithTypeVarTest
+3 errors
From 6f352740cb5e7c47d226fd4039cfb977c0622488 Mon Sep 17 00:00:00 2001
From: Thomas Schatzl
Date: Tue, 24 Oct 2023 14:49:06 +0000
Subject: [PATCH 03/19] 8318702: G1: Fix nonstandard indentation in
g1HeapTransition.cpp
Reviewed-by: iwalulya
---
src/hotspot/share/gc/g1/g1HeapTransition.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/hotspot/share/gc/g1/g1HeapTransition.cpp b/src/hotspot/share/gc/g1/g1HeapTransition.cpp
index 49ba19dfdba6d..a2097041b2093 100644
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp
@@ -143,11 +143,11 @@ void G1HeapTransition::print() {
usage = blk._usage;
assert(usage._eden_region_count == 0, "Expected no eden regions, but got " SIZE_FORMAT, usage._eden_region_count);
assert(usage._survivor_region_count == after._survivor_length, "Expected survivors to be " SIZE_FORMAT " but was " SIZE_FORMAT,
- after._survivor_length, usage._survivor_region_count);
+ after._survivor_length, usage._survivor_region_count);
assert(usage._old_region_count == after._old_length, "Expected old to be " SIZE_FORMAT " but was " SIZE_FORMAT,
- after._old_length, usage._old_region_count);
+ after._old_length, usage._old_region_count);
assert(usage._humongous_region_count == after._humongous_length, "Expected humongous to be " SIZE_FORMAT " but was " SIZE_FORMAT,
- after._humongous_length, usage._humongous_region_count);
+ after._humongous_length, usage._humongous_region_count);
}
log_regions("Eden", _before._eden_length, after._eden_length, eden_capacity_length_after_gc,
@@ -157,17 +157,17 @@ void G1HeapTransition::print() {
log_regions("Survivor", _before._survivor_length, after._survivor_length, survivor_capacity_length_before_gc,
_before._survivor_length_per_node, after._survivor_length_per_node);
log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
- usage._survivor_used / K, ((after._survivor_length * HeapRegion::GrainBytes) - usage._survivor_used) / K);
+ usage._survivor_used / K, ((after._survivor_length * HeapRegion::GrainBytes) - usage._survivor_used) / K);
log_info(gc, heap)("Old regions: " SIZE_FORMAT "->" SIZE_FORMAT,
_before._old_length, after._old_length);
log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
- usage._old_used / K, ((after._old_length * HeapRegion::GrainBytes) - usage._old_used) / K);
+ usage._old_used / K, ((after._old_length * HeapRegion::GrainBytes) - usage._old_used) / K);
log_info(gc, heap)("Humongous regions: " SIZE_FORMAT "->" SIZE_FORMAT,
_before._humongous_length, after._humongous_length);
log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
- usage._humongous_used / K, ((after._humongous_length * HeapRegion::GrainBytes) - usage._humongous_used) / K);
+ usage._humongous_used / K, ((after._humongous_length * HeapRegion::GrainBytes) - usage._humongous_used) / K);
MetaspaceUtils::print_metaspace_change(_before._meta_sizes);
}
From 116503754c4c4bdb91685955ef4456bc76f751c4 Mon Sep 17 00:00:00 2001
From: Naoto Sato
Date: Tue, 24 Oct 2023 16:54:57 +0000
Subject: [PATCH 04/19] 8318569: Add getter methods for Locale and Patterns in
ListFormat
Reviewed-by: joehw, rriggs, iris, mli
---
.../share/classes/java/text/ListFormat.java | 20 +++++++++
.../Format/ListFormat/TestListFormat.java | 41 ++++++++++++++++++-
2 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/java.base/share/classes/java/text/ListFormat.java b/src/java.base/share/classes/java/text/ListFormat.java
index d0b1b2aaf2aec..920cd9a076214 100644
--- a/src/java.base/share/classes/java/text/ListFormat.java
+++ b/src/java.base/share/classes/java/text/ListFormat.java
@@ -322,6 +322,26 @@ public static ListFormat getInstance(String[] patterns) {
return new ListFormat(Locale.ROOT, Arrays.copyOf(patterns, PATTERN_ARRAY_LENGTH));
}
+ /**
+ * {@return the {@code Locale} of this ListFormat}
+ *
+ * The {@code locale} is defined by {@link #getInstance(Locale, Type, Style)} or
+ * {@link #getInstance(String[])}.
+ */
+ public Locale getLocale() {
+ return locale;
+ }
+
+ /**
+ * {@return the patterns used in this ListFormat}
+ *
+ * The {@code patterns} are defined by {@link #getInstance(Locale, Type, Style)} or
+ * {@link #getInstance(String[])}.
+ */
+ public String[] getPatterns() {
+ return Arrays.copyOf(patterns, patterns.length);
+ }
+
/**
* {@return the string that consists of the input strings, concatenated with the
* patterns of this {@code ListFormat}}
diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java
index 2d260c9a94caf..eee6f6dac83ea 100644
--- a/test/jdk/java/text/Format/ListFormat/TestListFormat.java
+++ b/test/jdk/java/text/Format/ListFormat/TestListFormat.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8041488 8316974
+ * @bug 8041488 8316974 8318569
* @summary Tests for ListFormat class
* @run junit TestListFormat
*/
@@ -200,6 +200,7 @@ static Arguments[] parseObject_parsePos() {
arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE4),
};
}
+
static Arguments[] getInstance_3Arg_InheritPatterns() {
return new Arguments[] {
arguments(ListFormat.Type.STANDARD, ListFormat.Style.FULL),
@@ -213,6 +214,17 @@ static Arguments[] getInstance_3Arg_InheritPatterns() {
arguments(ListFormat.Type.UNIT, ListFormat.Style.NARROW),
};
}
+
+ static Arguments[] getLocale_localeDependent() {
+ return new Arguments[] {
+ arguments(Locale.ROOT),
+ arguments(Locale.US),
+ arguments(Locale.GERMANY),
+ arguments(Locale.JAPAN),
+ arguments(Locale.SIMPLIFIED_CHINESE),
+ };
+ }
+
@ParameterizedTest
@MethodSource
void getInstance_1Arg(String[] patterns, List input, String expected) throws ParseException {
@@ -235,6 +247,33 @@ void getInstance_3Arg(Locale l, ListFormat.Type type, ListFormat.Style style, St
compareResult(f, SAMPLE3, expected, roundTrip);
}
+ @Test
+ void getLocale_invariant() {
+ var f = ListFormat.getInstance(CUSTOM_PATTERNS_FULL);
+ assertEquals(Locale.ROOT, f.getLocale());
+ }
+
+ @Test
+ void getLocale_default() {
+ var f = ListFormat.getInstance();
+ assertEquals(Locale.getDefault(Locale.Category.FORMAT), f.getLocale());
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void getLocale_localeDependent(Locale l) {
+ var f = ListFormat.getInstance(l, ListFormat.Type.STANDARD, ListFormat.Style.FULL);
+ assertEquals(l, f.getLocale());
+ }
+
+ @Test
+ void getPatterns_immutability() {
+ var f = ListFormat.getInstance(CUSTOM_PATTERNS_FULL);
+ var p = f.getPatterns();
+ p[0] = null;
+ assertArrayEquals(CUSTOM_PATTERNS_FULL, f.getPatterns());
+ }
+
@Test
void format_3Arg() {
var f = ListFormat.getInstance();
From 1f2a80b78a6378b5b03f08a1e61614b8db40654c Mon Sep 17 00:00:00 2001
From: vamsi-parasa
Date: Tue, 24 Oct 2023 18:31:33 +0000
Subject: [PATCH 05/19] 8318306: java/util/Arrays/Sorting.java fails with
"Array is not sorted at 8228-th position: 8251.0 and 8153.0"
Reviewed-by: thartmann, jbhateja
---
src/hotspot/share/opto/library_call.cpp | 74 ++++++++++---------
.../intrinsics/SortingDeoptimizationTest.java | 72 ++++++++++++++++++
2 files changed, 112 insertions(+), 34 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/intrinsics/SortingDeoptimizationTest.java
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index 4a9d7fb161667..62d785809531e 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -5367,8 +5367,6 @@ void LibraryCallKit::create_new_uncommon_trap(CallStaticJavaNode* uncommon_trap_
//------------------------------inline_array_partition-----------------------
bool LibraryCallKit::inline_array_partition() {
- const char *stubName = "array_partition_stub";
-
Node* elementType = null_check(argument(0));
Node* obj = argument(1);
Node* offset = argument(2);
@@ -5377,38 +5375,48 @@ bool LibraryCallKit::inline_array_partition() {
Node* indexPivot1 = argument(6);
Node* indexPivot2 = argument(7);
- const TypeInstPtr* elem_klass = gvn().type(elementType)->isa_instptr();
- ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type();
- BasicType bt = elem_type->basic_type();
- address stubAddr = nullptr;
- stubAddr = StubRoutines::select_array_partition_function();
- // stub not loaded
- if (stubAddr == nullptr) {
- return false;
- }
- // get the address of the array
- const TypeAryPtr* obj_t = _gvn.type(obj)->isa_aryptr();
- if (obj_t == nullptr || obj_t->elem() == Type::BOTTOM ) {
- return false; // failed input validation
- }
- Node* obj_adr = make_unsafe_address(obj, offset);
+ Node* pivotIndices = nullptr;
- // create the pivotIndices array of type int and size = 2
- Node* size = intcon(2);
- Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
- Node* pivotIndices = new_array(klass_node, size, 0); // no arguments to push
- AllocateArrayNode* alloc = tightly_coupled_allocation(pivotIndices);
- guarantee(alloc != nullptr, "created above");
- Node* pivotIndices_adr = basic_plus_adr(pivotIndices, arrayOopDesc::base_offset_in_bytes(T_INT));
+ // Set the original stack and the reexecute bit for the interpreter to reexecute
+ // the bytecode that invokes DualPivotQuicksort.partition() if deoptimization happens.
+ { PreserveReexecuteState preexecs(this);
+ jvms()->set_should_reexecute(true);
- // pass the basic type enum to the stub
- Node* elemType = intcon(bt);
+ const TypeInstPtr* elem_klass = gvn().type(elementType)->isa_instptr();
+ ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type();
+ BasicType bt = elem_type->basic_type();
+ address stubAddr = nullptr;
+ stubAddr = StubRoutines::select_array_partition_function();
+ // stub not loaded
+ if (stubAddr == nullptr) {
+ return false;
+ }
+ // get the address of the array
+ const TypeAryPtr* obj_t = _gvn.type(obj)->isa_aryptr();
+ if (obj_t == nullptr || obj_t->elem() == Type::BOTTOM ) {
+ return false; // failed input validation
+ }
+ Node* obj_adr = make_unsafe_address(obj, offset);
- // Call the stub
- make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::array_partition_Type(),
- stubAddr, stubName, TypePtr::BOTTOM,
- obj_adr, elemType, fromIndex, toIndex, pivotIndices_adr,
- indexPivot1, indexPivot2);
+ // create the pivotIndices array of type int and size = 2
+ Node* size = intcon(2);
+ Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+ pivotIndices = new_array(klass_node, size, 0); // no arguments to push
+ AllocateArrayNode* alloc = tightly_coupled_allocation(pivotIndices);
+ guarantee(alloc != nullptr, "created above");
+ Node* pivotIndices_adr = basic_plus_adr(pivotIndices, arrayOopDesc::base_offset_in_bytes(T_INT));
+
+ // pass the basic type enum to the stub
+ Node* elemType = intcon(bt);
+
+ // Call the stub
+ const char *stubName = "array_partition_stub";
+ make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::array_partition_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ obj_adr, elemType, fromIndex, toIndex, pivotIndices_adr,
+ indexPivot1, indexPivot2);
+
+ } // original reexecute is set back here
if (!stopped()) {
set_result(pivotIndices);
@@ -5421,9 +5429,6 @@ bool LibraryCallKit::inline_array_partition() {
//------------------------------inline_array_sort-----------------------
bool LibraryCallKit::inline_array_sort() {
- const char *stubName;
- stubName = "arraysort_stub";
-
Node* elementType = null_check(argument(0));
Node* obj = argument(1);
Node* offset = argument(2);
@@ -5451,6 +5456,7 @@ bool LibraryCallKit::inline_array_sort() {
Node* elemType = intcon(bt);
// Call the stub.
+ const char *stubName = "arraysort_stub";
make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::array_sort_Type(),
stubAddr, stubName, TypePtr::BOTTOM,
obj_adr, elemType, fromIndex, toIndex);
diff --git a/test/hotspot/jtreg/compiler/intrinsics/SortingDeoptimizationTest.java b/test/hotspot/jtreg/compiler/intrinsics/SortingDeoptimizationTest.java
new file mode 100644
index 0000000000000..f9fbcfefb9953
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/intrinsics/SortingDeoptimizationTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023, 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 8318306
+ * @run main/othervm/timeout=200 -XX:+IgnoreUnrecognizedVMOptions -Xcomp -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -XX:+DeoptimizeALot SortingDeoptimizationTest 1e-2 100 50
+ * @summary Exercise Arrays.parallelSort when -XX:+DeoptimizeALot is enabled
+ *
+ */
+
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Random;
+
+public class SortingDeoptimizationTest {
+
+ private static final PrintStream err = System.err;
+ private static final PrintStream out = System.out;
+
+ public static void main(String[] args) {
+ int MAX = 2147483647; // 2^32 - 1
+ float fraction = Float.parseFloat(args[0]);
+ int size = (int) (fraction * MAX); // size is a fraction of the MAX size
+ int iters = Integer.parseInt(args[1]); // number of iterations
+ int max = args.length > 2 ? Integer.parseInt(args[2]) : -1 ; // max value for the array elements
+ long seed = 0xC0FFEE;
+ Random rand = new Random(seed);
+
+ for (int i = 0; i < iters; i++) {
+ boolean isSorted = runSort(size, max, rand);
+ out.println("Iteration " + i + ": is sorted? -> "+ isSorted);
+ if (!isSorted) fail("Array is not correctly sorted.");
+ }
+ }
+
+ private static void fail(String message) {
+ err.format("\n*** TEST FAILED ***\n\n%s\n\n", message);
+ throw new RuntimeException("Test failed");
+ }
+
+ private static boolean runSort(int size, int max, Random rand) {
+ int[] a = new int[size];
+ for (int i = 0; i < a.length; i++) a[i] = max > 0 ? rand.nextInt(max) : rand.nextInt();
+ // call parallel sort
+ Arrays.parallelSort(a);
+ // check if sorted
+ boolean isSorted = true;
+ for (int i = 0; i < (a.length -1); i++) isSorted = isSorted && (a[i] <= a[i+1]);
+ return isSorted;
+ }
+}
From 1ddf826aea7fd18209336dce550821638d5ef89c Mon Sep 17 00:00:00 2001
From: Weijun Wang
Date: Tue, 24 Oct 2023 18:32:01 +0000
Subject: [PATCH 06/19] 8316964: Security tools should not call System.exit
Reviewed-by: valeriep
---
.../sun/security/tools/keytool/Main.java | 27 ++-
.../security/krb5/internal/tools/Kinit.java | 78 +++----
.../krb5/internal/tools/KinitOptions.java | 7 +-
.../security/krb5/internal/tools/Klist.java | 190 +++++++++---------
.../security/krb5/internal/tools/Ktab.java | 89 +++++---
.../sun/security/tools/jarsigner/Main.java | 62 +++---
.../sun/security/krb5/tools/ExitOrNot.java | 61 ++++++
.../security/tools/jarsigner/ExitOrNot.java | 52 +++++
8 files changed, 358 insertions(+), 208 deletions(-)
create mode 100644 test/jdk/sun/security/krb5/tools/ExitOrNot.java
create mode 100644 test/jdk/sun/security/tools/jarsigner/ExitOrNot.java
diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java
index 2effa3425d71a..b094acc51fe96 100644
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java
@@ -405,26 +405,38 @@ public String toString() {
collator.setStrength(Collator.PRIMARY);
}
- private Main() { }
-
public static void main(String[] args) throws Exception {
Main kt = new Main();
- kt.run(args, System.out);
+ int exitCode = kt.run(args, System.out);
+ if (exitCode != 0) {
+ System.exit(exitCode);
+ }
+ }
+
+ private static class ExitException extends RuntimeException {
+ @java.io.Serial
+ static final long serialVersionUID = 0L;
+ private final int errorCode;
+ public ExitException(int errorCode) {
+ this.errorCode = errorCode;
+ }
}
- private void run(String[] args, PrintStream out) throws Exception {
+ public int run(String[] args, PrintStream out) throws Exception {
try {
- args = parseArgs(args);
+ parseArgs(args);
if (command != null) {
doCommands(out);
}
+ } catch (ExitException ee) {
+ return ee.errorCode;
} catch (Exception e) {
System.out.println(rb.getString("keytool.error.") + e);
if (verbose) {
e.printStackTrace(System.out);
}
if (!debug) {
- System.exit(1);
+ return 1;
} else {
throw e;
}
@@ -441,6 +453,7 @@ private void run(String[] args, PrintStream out) throws Exception {
ksStream.close();
}
}
+ return 0;
}
/**
@@ -5247,7 +5260,7 @@ private void tinyHelp() {
if (debug) {
throw new RuntimeException("NO BIG ERROR, SORRY");
} else {
- System.exit(1);
+ throw new ExitException(1);
}
}
diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java
index 813939643c3cf..a14ece6ee0e02 100644
--- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java
+++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -92,14 +92,44 @@ public class Kinit {
*/
public static void main(String[] args) {
- try {
- Kinit self = new Kinit(args);
+ Kinit kinit = new Kinit();
+ int exitCode = kinit.run(args);
+ if (exitCode != 0) {
+ System.exit(exitCode);
}
- catch (Exception e) {
- String msg = null;
- if (e instanceof KrbException) {
- msg = ((KrbException)e).krbErrorMessage() + " " +
- ((KrbException)e).returnCodeMessage();
+ }
+
+ /**
+ * Run the Kinit command.
+ * @param args array of ticket request options.
+ * Available options are: -f, -p, -c, principal, password.
+ * @return the exit code
+ */
+ public int run(String[] args) {
+ try {
+ if (args == null || args.length == 0) {
+ options = new KinitOptions();
+ } else {
+ options = new KinitOptions(args);
+ }
+ switch (options.action) {
+ case 0:
+ // Help, already displayed in new KinitOptions().
+ break;
+ case 1:
+ acquire();
+ break;
+ case 2:
+ renew();
+ break;
+ default:
+ throw new KrbException("kinit does not support action "
+ + options.action);
+ }
+ } catch (Exception e) {
+ String msg;
+ if (e instanceof KrbException ke) {
+ msg = ke.krbErrorMessage() + " " + ke.returnCodeMessage();
} else {
msg = e.getMessage();
}
@@ -109,37 +139,9 @@ public static void main(String[] args) {
System.out.println("Exception: " + e);
}
e.printStackTrace();
- System.exit(-1);
- }
- return;
- }
-
- /**
- * Constructs a new Kinit object.
- * @param args array of ticket request options.
- * Available options are: -f, -p, -c, principal, password.
- * @exception IOException if an I/O error occurs.
- * @exception RealmException if the Realm could not be instantiated.
- * @exception KrbException if error occurs during Kerberos operation.
- */
- private Kinit(String[] args)
- throws IOException, RealmException, KrbException {
- if (args == null || args.length == 0) {
- options = new KinitOptions();
- } else {
- options = new KinitOptions(args);
- }
- switch (options.action) {
- case 1:
- acquire();
- break;
- case 2:
- renew();
- break;
- default:
- throw new KrbException("kinit does not support action "
- + options.action);
+ return -1;
}
+ return 0;
}
private void renew()
diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java
index 5cfc574d95acf..445b806bb50cf 100644
--- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java
+++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
*/
class KinitOptions {
- // 1. acquire, 2. renew, 3. validate
+ // 0. Help, 1. acquire, 2. renew, 3. validate
public int action = 1;
// forwardable and proxiable flags have two states:
@@ -143,7 +143,8 @@ public KinitOptions(String[] args)
// -help: legacy.
args[i].equalsIgnoreCase("-help")) {
printHelp();
- System.exit(0);
+ action = 0;
+ return;
} else if (p == null) { // Haven't yet processed a "principal"
p = args[i];
try {
diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java
index 5a0c3bee0776e..16c9fd99ec406 100644
--- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java
+++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2023, 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
@@ -78,115 +78,111 @@ public class Klist {
*/
public static void main(String[] args) {
Klist klist = new Klist();
+ int exitCode = klist.run(args);
+ if (exitCode != 0) {
+ System.exit(exitCode);
+ }
+ }
+
+ public int run(String[] args) {
if ((args == null) || (args.length == 0)) {
- klist.action = 'c'; // default will list default credentials cache.
+ action = 'c'; // default will list default credentials cache.
} else {
- klist.processArgs(args);
+ Character arg;
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("-?") ||
+ args[i].equals("-h") ||
+ args[i].equals("--help")) {
+ printHelp();
+ return 0;
+ }
+ if ((args[i].length() >= 2) && (args[i].startsWith("-"))) {
+ arg = Character.valueOf(args[i].charAt(1));
+ switch (arg.charValue()) {
+ case 'c':
+ action = 'c';
+ break;
+ case 'k':
+ action = 'k';
+ break;
+ case 'a':
+ options[2] = 'a';
+ break;
+ case 'n':
+ options[3] = 'n';
+ break;
+ case 'f':
+ options[1] = 'f';
+ break;
+ case 'e':
+ options[0] = 'e';
+ break;
+ case 'K':
+ options[1] = 'K';
+ break;
+ case 't':
+ options[2] = 't';
+ break;
+ default:
+ System.out.println("Invalid argument: " + args[i]);
+ printHelp();
+ return -1;
+ }
+ } else {
+ if (!args[i].startsWith("-") && (i == args.length - 1)) {
+ // the argument is the last one.
+ name = args[i];
+ } else {
+ System.out.println("Invalid argument: " + args[i]);
+ printHelp(); // incorrect input format.
+ return -1;
+ }
+ }
+ }
}
- switch (klist.action) {
+ switch (action) {
case 'c':
- if (klist.name == null) {
- klist.target = CredentialsCache.getInstance();
- klist.name = CredentialsCache.cacheName();
+ if (name == null) {
+ target = CredentialsCache.getInstance();
+ name = CredentialsCache.cacheName();
} else
- klist.target = CredentialsCache.getInstance(klist.name);
+ target = CredentialsCache.getInstance(name);
- if (klist.target != null) {
- klist.displayCache();
+ if (target != null) {
+ return displayCache();
} else {
- klist.displayMessage("Credentials cache");
- System.exit(-1);
+ return displayError("Credentials cache");
}
- break;
case 'k':
- KeyTab ktab = KeyTab.getInstance(klist.name);
+ KeyTab ktab = KeyTab.getInstance(name);
if (ktab.isMissing()) {
- System.out.println("KeyTab " + klist.name + " not found.");
- System.exit(-1);
+ System.out.println("KeyTab " + name + " not found.");
+ return -1;
} else if (!ktab.isValid()) {
- System.out.println("KeyTab " + klist.name
+ System.out.println("KeyTab " + name
+ " format not supported.");
- System.exit(-1);
+ return -1;
}
- klist.target = ktab;
- klist.name = ktab.tabName();
- klist.displayTab();
- break;
+ target = ktab;
+ name = ktab.tabName();
+ return displayTab();
default:
- if (klist.name != null) {
- klist.printHelp();
- System.exit(-1);
- } else {
- klist.target = CredentialsCache.getInstance();
- klist.name = CredentialsCache.cacheName();
- if (klist.target != null) {
- klist.displayCache();
- } else {
- klist.displayMessage("Credentials cache");
- System.exit(-1);
- }
- }
- }
- }
-
- /**
- * Parses the command line arguments.
- */
- void processArgs(String[] args) {
- Character arg;
- for (int i = 0; i < args.length; i++) {
- if (args[i].equals("-?") ||
- args[i].equals("-h") ||
- args[i].equals("--help")) {
+ if (name != null) {
printHelp();
- System.exit(0);
- }
- if ((args[i].length() >= 2) && (args[i].startsWith("-"))) {
- arg = Character.valueOf(args[i].charAt(1));
- switch (arg.charValue()) {
- case 'c':
- action = 'c';
- break;
- case 'k':
- action = 'k';
- break;
- case 'a':
- options[2] = 'a';
- break;
- case 'n':
- options[3] = 'n';
- break;
- case 'f':
- options[1] = 'f';
- break;
- case 'e':
- options[0] = 'e';
- break;
- case 'K':
- options[1] = 'K';
- break;
- case 't':
- options[2] = 't';
- break;
- default:
- printHelp();
- System.exit(-1);
- }
-
+ return -1;
} else {
- if (!args[i].startsWith("-") && (i == args.length - 1)) {
- // the argument is the last one.
- name = args[i];
- arg = null;
+ target = CredentialsCache.getInstance();
+ name = CredentialsCache.cacheName();
+ if (target != null) {
+ return displayCache();
} else {
- printHelp(); // incorrect input format.
- System.exit(-1);
+ return displayError("Credentials cache");
}
}
}
}
- void displayTab() {
+ int displayTab() {
KeyTab table = (KeyTab)target;
KeyTabEntry[] entries = table.getEntries();
if (entries.length == 0) {
@@ -201,7 +197,7 @@ void displayTab() {
entries.length + " entries found.\n");
for (int i = 0; i < entries.length; i++) {
System.out.println("[" + (i + 1) + "] " +
- "Service principal: " +
+ "Service principal: " +
entries[i].getService().toString());
System.out.println("\t KVNO: " +
entries[i].getKey().getKeyVersionNumber());
@@ -221,18 +217,19 @@ void displayTab() {
}
}
}
+ return 0;
}
- void displayCache() {
+ int displayCache() {
CredentialsCache cache = (CredentialsCache)target;
sun.security.krb5.internal.ccache.Credentials[] creds =
cache.getCredsList();
if (creds == null) {
System.out.println ("No credentials available in the cache " +
name);
- System.exit(-1);
+ return -1;
}
- System.out.println("\nCredentials cache: " + name);
+ System.out.println("\nCredentials cache: " + name);
String defaultPrincipal = cache.getPrimaryPrincipal().toString();
int num = creds.length;
@@ -327,7 +324,7 @@ void displayCache() {
if (DEBUG) {
e.printStackTrace();
}
- System.exit(-1);
+ return -1;
}
}
} else {
@@ -342,14 +339,17 @@ void displayCache() {
System.out.println(" " + e);
}
}
+
+ return 0;
}
- void displayMessage(String target) {
+ int displayError(String target) {
if (name == null) {
System.out.println("Default " + target + " not found.");
} else {
System.out.println(target + " " + name + " not found.");
}
+ return -1;
}
/**
* Reformats the date from the form -
@@ -359,7 +359,7 @@ void displayMessage(String target) {
* the day, mm is the minute within the hour,
* ss is the second within the minute, zzz is the time zone,
* and yyyy is the year.
- * @param date the string form of Date object.
+ * @param kt the string form of Date object.
*/
private String format(KerberosTime kt) {
String date = kt.toDate().toString();
diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java
index df12b2d6c11dd..21002f3369a03 100644
--- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java
+++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2023, 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
@@ -73,52 +73,76 @@ public class Ktab {
*/
public static void main(String[] args) {
Ktab ktab = new Ktab();
+ int exitCode = ktab.run(args);
+ if (exitCode != 0) {
+ System.exit(exitCode);
+ }
+ }
+
+ private static class ExitException extends RuntimeException {
+ @java.io.Serial
+ static final long serialVersionUID = 0L;
+ private final int errorCode;
+ public ExitException(int errorCode) {
+ this.errorCode = errorCode;
+ }
+ }
+
+ public int run(String[] args) {
+ try {
+ run0(args);
+ return 0;
+ } catch (ExitException ee) {
+ return ee.errorCode;
+ }
+ }
+
+ private void run0(String[] args) throws ExitException {
if ((args.length == 1) &&
((args[0].equalsIgnoreCase("-?")) ||
(args[0].equalsIgnoreCase("-h")) ||
(args[0].equalsIgnoreCase("--help")) ||
// -help: legacy.
(args[0].equalsIgnoreCase("-help")))) {
- ktab.printHelp();
- System.exit(0);
+ printHelp();
return;
} else if ((args == null) || (args.length == 0)) {
- ktab.action = 'l';
+ action = 'l';
} else {
- ktab.processArgs(args);
+ processArgs(args);
}
- ktab.table = KeyTab.getInstance(ktab.name);
- if (ktab.table.isMissing() && ktab.action != 'a') {
- if (ktab.name == null) {
+ table = KeyTab.getInstance(name);
+ if (table.isMissing() && action != 'a') {
+ if (name == null) {
System.out.println("No default key table exists.");
} else {
System.out.println("Key table " +
- ktab.name + " does not exist.");
+ name + " does not exist.");
}
- System.exit(-1);
+ throw new ExitException(-1);
}
- if (!ktab.table.isValid()) {
- if (ktab.name == null) {
+ if (!table.isValid()) {
+ if (name == null) {
System.out.println("The format of the default key table " +
" is incorrect.");
} else {
System.out.println("The format of key table " +
- ktab.name + " is incorrect.");
+ name + " is incorrect.");
}
- System.exit(-1);
+ throw new ExitException(-1);
}
- switch (ktab.action) {
+ switch (action) {
case 'l':
- ktab.listKt();
+ listKt();
break;
case 'a':
- ktab.addEntry();
+ addEntry();
break;
case 'd':
- ktab.deleteEntry();
+ deleteEntry();
break;
default:
- ktab.error("A command must be provided");
+ error("A command must be provided");
}
}
@@ -267,7 +291,7 @@ void processArgs(String[] args) {
void addEntry() {
if (salt != null && fopt) {
System.err.println("-s and -f cannot coexist when adding a keytab entry.");
- System.exit(-1);
+ throw new ExitException(-1);
}
PrincipalName pname = null;
try {
@@ -276,7 +300,7 @@ void addEntry() {
System.err.println("Failed to add " + principal +
" to keytab.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
}
if (password == null) {
try {
@@ -288,7 +312,7 @@ void addEntry() {
} catch (IOException e) {
System.err.println("Failed to read the password.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
}
}
@@ -313,11 +337,11 @@ void addEntry() {
} catch (KrbException e) {
System.err.println("Failed to add " + principal + " to keytab.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
} catch (IOException e) {
System.err.println("Failed to save new entry.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
}
}
@@ -399,22 +423,23 @@ void deleteEntry() {
System.out.flush();
answer = cis.readLine();
if (answer.equalsIgnoreCase("Y") ||
- answer.equalsIgnoreCase("Yes"));
- else {
+ answer.equalsIgnoreCase("Yes")) {
+ ;
+ } else {
// no error, the user did not want to delete the entry
- System.exit(0);
+ return;
}
}
} catch (KrbException e) {
System.err.println("Error occurred while deleting the entry. "+
"Deletion failed.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
} catch (IOException e) {
System.err.println("Error occurred while deleting the entry. "+
" Deletion failed.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
}
int count = table.deleteEntries(pname, etype, vDel);
@@ -422,7 +447,7 @@ void deleteEntry() {
if (count == 0) {
System.err.println("No matched entry in the keytab. " +
"Deletion fails.");
- System.exit(-1);
+ throw new ExitException(-1);
} else {
try {
table.save();
@@ -430,7 +455,7 @@ void deleteEntry() {
System.err.println("Error occurs while saving the keytab. " +
"Deletion fails.");
e.printStackTrace();
- System.exit(-1);
+ throw new ExitException(-1);
}
System.out.println("Done! " + count + " entries removed.");
}
@@ -441,7 +466,7 @@ void error(String... errors) {
System.out.println("Error: " + error + ".");
}
printHelp();
- System.exit(-1);
+ throw new ExitException(-1);
}
/**
diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
index 117fea688c71b..ed2c9be854310 100644
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
@@ -135,7 +135,19 @@ public class Main {
// This is the entry that get launched by the security tool jarsigner.
public static void main(String args[]) throws Exception {
Main js = new Main();
- js.run(args);
+ int exitCode = js.run(args);
+ if (exitCode != 0) {
+ System.exit(exitCode);
+ }
+ }
+
+ private static class ExitException extends RuntimeException {
+ @java.io.Serial
+ static final long serialVersionUID = 0L;
+ private final int errorCode;
+ public ExitException(int errorCode) {
+ this.errorCode = errorCode;
+ }
}
X509Certificate[] certChain; // signer's cert chain (when composing)
@@ -230,13 +242,13 @@ public static void main(String args[]) throws Exception {
PKIXBuilderParameters pkixParameters;
Set trustedCerts = new HashSet<>();
- public void run(String args[]) {
+ public int run(String args[]) {
try {
- args = parseArgs(args);
+ parseArgs(args);
// Try to load and install the specified providers
if (providers != null) {
- for (String provName: providers) {
+ for (String provName : providers) {
try {
KeyStoreUtil.loadProviderByName(provName,
providerArgs.get(provName));
@@ -263,7 +275,7 @@ public void run(String args[]) {
} else {
cl = ClassLoader.getSystemClassLoader();
}
- for (String provClass: providerClasses) {
+ for (String provClass : providerClasses) {
try {
KeyStoreUtil.loadProviderByClass(provClass,
providerArgs.get(provClass), cl);
@@ -285,19 +297,9 @@ public void run(String args[]) {
loadKeyStore(keystore, false);
} catch (Exception e) {
if ((keystore != null) || (storepass != null)) {
- System.out.println(rb.getString("jarsigner.error.") +
- e.getMessage());
- if (debug) {
- e.printStackTrace();
- }
- System.exit(1);
+ throw e;
}
}
- /* if (debug) {
- SignatureFileVerifier.setDebug(true);
- ManifestEntryVerifier.setDebug(true);
- }
- */
verifyJar(jarfile);
} else {
loadKeyStore(keystore, true);
@@ -305,12 +307,14 @@ public void run(String args[]) {
signJar(jarfile, alias);
}
+ } catch (ExitException ee) {
+ return ee.errorCode;
} catch (Exception e) {
System.out.println(rb.getString("jarsigner.error.") + e);
if (debug) {
e.printStackTrace();
}
- System.exit(1);
+ return 1;
} finally {
// zero-out private key password
if (keypass != null) {
@@ -343,10 +347,10 @@ public void run(String args[]) {
if (tsaChainNotValidated) {
exitCode |= 64;
}
- if (exitCode != 0) {
- System.exit(exitCode);
- }
+ return exitCode;
}
+
+ return 0;
}
/*
@@ -612,12 +616,12 @@ static void usageNoArg() {
static void usage() {
System.out.println();
System.out.println(rb.getString("Please.type.jarsigner.help.for.usage"));
- System.exit(1);
+ throw new ExitException(1);
}
static void doPrintVersion() {
System.out.println("jarsigner " + System.getProperty("java.version"));
- System.exit(0);
+ throw new ExitException(0);
}
static void fullusage() {
@@ -719,7 +723,7 @@ static void fullusage() {
(".print.this.help.message"));
System.out.println();
- System.exit(0);
+ throw new ExitException(0);
}
void verifyJar(String jarName)
@@ -1105,19 +1109,11 @@ void verifyJar(String jarName)
} else {
displayMessagesAndResult(false);
}
- return;
- } catch (Exception e) {
- System.out.println(rb.getString("jarsigner.") + e);
- if (debug) {
- e.printStackTrace();
- }
} finally { // close the resource
if (jf != null) {
jf.close();
}
}
-
- System.exit(1);
}
private void displayMessagesAndResult(boolean isSigning) {
@@ -2469,7 +2465,7 @@ void getAliasInfo(String alias) throws Exception {
void error(String message) {
System.out.println(rb.getString("jarsigner.")+message);
- System.exit(1);
+ throw new ExitException(1);
}
@@ -2478,7 +2474,7 @@ void error(String message, Throwable e) {
if (debug) {
e.printStackTrace();
}
- System.exit(1);
+ throw new ExitException(1);
}
/**
diff --git a/test/jdk/sun/security/krb5/tools/ExitOrNot.java b/test/jdk/sun/security/krb5/tools/ExitOrNot.java
new file mode 100644
index 0000000000000..9f3000dcb75ae
--- /dev/null
+++ b/test/jdk/sun/security/krb5/tools/ExitOrNot.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023, 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 8316964
+ * @summary check exit code in kinit, klist, and ktab
+ * @requires os.family == "windows"
+ * @library /test/lib
+ * @modules java.security.jgss/sun.security.krb5.internal.tools
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Platform;
+import jdk.test.lib.SecurityTools;
+
+public class ExitOrNot {
+
+ private static final int BAD = Platform.isWindows() ? -1 : 255;
+
+ public static void main(String[] args) throws Exception {
+
+ // launching the tool still exits
+ SecurityTools.kinit("u@R p1 p2")
+ .shouldHaveExitValue(BAD);
+
+ SecurityTools.klist("-x")
+ .shouldHaveExitValue(BAD);
+
+ SecurityTools.ktab("-x")
+ .shouldHaveExitValue(BAD);
+
+ // calling the run() methods returns the exit code
+ Asserts.assertEQ(new sun.security.krb5.internal.tools.Kinit()
+ .run("u@R p1 p2".split(" ")), -1);
+ Asserts.assertEQ(new sun.security.krb5.internal.tools.Klist()
+ .run("-x".split(" ")), -1);
+ Asserts.assertEQ(new sun.security.krb5.internal.tools.Ktab()
+ .run("-x".split(" ")), -1);
+ }
+}
diff --git a/test/jdk/sun/security/tools/jarsigner/ExitOrNot.java b/test/jdk/sun/security/tools/jarsigner/ExitOrNot.java
new file mode 100644
index 0000000000000..ae55074f3a50c
--- /dev/null
+++ b/test/jdk/sun/security/tools/jarsigner/ExitOrNot.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023, 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 8316964
+ * @summary check exit code in jarsigner and keytool
+ * @library /test/lib
+ * @modules java.base/sun.security.tools.keytool
+ * jdk.jartool/sun.security.tools.jarsigner
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.SecurityTools;
+
+public class ExitOrNot {
+ public static void main(String[] args) throws Exception {
+
+ // launching the tool still exits
+ SecurityTools.jarsigner("1 2 3")
+ .shouldHaveExitValue(1);
+ SecurityTools.keytool("-x")
+ .shouldHaveExitValue(1);
+
+ // calling the run() methods no longer
+ Asserts.assertEQ(new sun.security.tools.jarsigner.Main()
+ .run("1 2 3".split(" ")), 1);
+
+ Asserts.assertEQ(new sun.security.tools.keytool.Main()
+ .run("-x".split(" "), System.out), 1);
+ }
+}
From 9c819fd3b7e564b53514185573f4ffe28368b46b Mon Sep 17 00:00:00 2001
From: Eamonn McManus
Date: Tue, 24 Oct 2023 18:32:33 +0000
Subject: [PATCH 07/19] 8318051: Duration.between uses exceptions for control
flow
Reviewed-by: rriggs
---
.../share/classes/java/time/Duration.java | 33 ++++++++++---------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java
index c1894e2db5a7c..ab46159efd6a2 100644
--- a/src/java.base/share/classes/java/time/Duration.java
+++ b/src/java.base/share/classes/java/time/Duration.java
@@ -486,23 +486,26 @@ private static Duration create(boolean negate, long daysAsSecs, long hoursAsSecs
* @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
*/
public static Duration between(Temporal startInclusive, Temporal endExclusive) {
- try {
+ long secs = startInclusive.until(endExclusive, SECONDS);
+ if (secs == 0) {
+ // We don't know which Temporal is earlier, so the adjustment below would not work.
+ // But we do know that there's no danger of until(NANOS) overflowing in that case.
return ofNanos(startInclusive.until(endExclusive, NANOS));
- } catch (DateTimeException | ArithmeticException ex) {
- long secs = startInclusive.until(endExclusive, SECONDS);
- long nanos;
- try {
- nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
- if (secs > 0 && nanos < 0) {
- secs++;
- } else if (secs < 0 && nanos > 0) {
- secs--;
- }
- } catch (DateTimeException ex2) {
- nanos = 0;
- }
- return ofSeconds(secs, nanos);
}
+ long nanos;
+ try {
+ nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
+ } catch (DateTimeException ex2) {
+ nanos = 0;
+ }
+ if (nanos < 0 && secs > 0) {
+ // ofSeconds will subtract one even though until(SECONDS) already gave the correct
+ // number of seconds. So compensate. Similarly for the secs < 0 case below.
+ secs++;
+ } else if (nanos > 0 && secs < 0) {
+ secs--;
+ }
+ return ofSeconds(secs, nanos);
}
//-----------------------------------------------------------------------
From f1dfdc1a79f3a16eae58d15d1945541a08f7e145 Mon Sep 17 00:00:00 2001
From: Alexander Matveev
Date: Tue, 24 Oct 2023 21:41:20 +0000
Subject: [PATCH 08/19] 8311877: [macos] Add CLI options to provide signing
identity directly to codesign and productbuild
Reviewed-by: asemenyuk
---
.../jdk/jpackage/internal/MacAppBundler.java | 26 +++-
.../jpackage/internal/MacAppImageBuilder.java | 50 ++++++--
.../internal/MacBaseInstallerBundler.java | 7 ++
.../jdk/jpackage/internal/MacPkgBundler.java | 54 ++++++--
.../resources/MacResources.properties | 3 +-
.../resources/MacResources_de.properties | 3 +-
.../resources/MacResources_ja.properties | 3 +-
.../resources/MacResources_zh_CN.properties | 3 +-
.../jdk/jpackage/internal/Arguments.java | 24 ++++
.../jpackage/internal/BundlerParamInfo.java | 28 +++--
.../jdk/jpackage/internal/ValidOptions.java | 6 +-
.../resources/HelpResources.properties | 16 ++-
.../resources/MainResources.properties | 5 +-
.../resources/MainResources_de.properties | 3 +-
.../resources/MainResources_ja.properties | 3 +-
.../resources/MainResources_zh_CN.properties | 3 +-
.../jpackage/macosx/SigningAppImageTest.java | 26 ++--
.../macosx/SigningAppImageTwoStepsTest.java | 34 ++++--
.../jpackage/macosx/SigningOptionsTest.java | 115 ++++++++++++++++++
...SigningPackageFromTwoStepAppImageTest.java | 53 ++++++--
.../jpackage/macosx/SigningPackageTest.java | 86 +++++++++++--
.../macosx/SigningPackageTwoStepTest.java | 51 ++++++--
.../jpackage/macosx/base/SigningBase.java | 32 +++--
.../tests/PredefinedAppImageErrorTest.java | 2 +-
24 files changed, 531 insertions(+), 105 deletions(-)
create mode 100644 test/jdk/tools/jpackage/macosx/SigningOptionsTest.java
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
index cf031cb47a5ee..06796db98847a 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
@@ -85,6 +85,13 @@ public MacAppBundler() {
},
(s, p) -> s);
+ public static final BundlerParamInfo APP_IMAGE_SIGN_IDENTITY =
+ new StandardBundlerParam<>(
+ Arguments.CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY.getId(),
+ String.class,
+ params -> "",
+ null);
+
public static final BundlerParamInfo BUNDLE_ID_SIGNING_PREFIX =
new StandardBundlerParam<>(
Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
@@ -127,14 +134,21 @@ private static void doValidate(Map params)
// reject explicitly set sign to true and no valid signature key
if (Optional.ofNullable(
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
- String signingIdentity =
- DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
- if (signingIdentity == null) {
- throw new ConfigException(
- I18N.getString("error.explicit-sign-no-cert"),
- I18N.getString("error.explicit-sign-no-cert.advice"));
+ // Validate DEVELOPER_ID_APP_SIGNING_KEY only if user provided
+ // SIGNING_KEY_USER.
+ if (!SIGNING_KEY_USER.getIsDefaultValue(params)) { // --mac-signing-key-user-name
+ String signingIdentity =
+ DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
+ if (signingIdentity == null) {
+ throw new ConfigException(
+ I18N.getString("error.explicit-sign-no-cert"),
+ I18N.getString("error.explicit-sign-no-cert.advice"));
+ }
}
+ // No need to validate --mac-app-image-sign-identity, since it is
+ // pass through option.
+
// Signing will not work without Xcode with command line developer tools
try {
ProcessBuilder pb = new ProcessBuilder("/usr/bin/xcrun", "--help");
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
index d9250ae147409..ea86c41d98128 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
@@ -25,8 +25,10 @@
package jdk.jpackage.internal;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -53,7 +55,10 @@
import jdk.internal.util.OSVersion;
import static jdk.jpackage.internal.MacAppBundler.BUNDLE_ID_SIGNING_PREFIX;
import static jdk.jpackage.internal.MacAppBundler.DEVELOPER_ID_APP_SIGNING_KEY;
+import static jdk.jpackage.internal.MacAppBundler.APP_IMAGE_SIGN_IDENTITY;
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
+import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
+import static jdk.jpackage.internal.MacBaseInstallerBundler.INSTALLER_SIGN_IDENTITY;
import static jdk.jpackage.internal.OverridableResource.createResource;
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
@@ -395,12 +400,25 @@ private void doSigning(Map params)
} catch (InterruptedException e) {
Log.error(e.getMessage());
}
- String signingIdentity =
- DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
+ String signingIdentity = null;
+ // Try --mac-app-image-sign-identity first if set
+ if (!APP_IMAGE_SIGN_IDENTITY.getIsDefaultValue(params)) {
+ signingIdentity = APP_IMAGE_SIGN_IDENTITY.fetchFrom(params);
+ } else {
+ // Check if INSTALLER_SIGN_IDENTITY is set and if it is set
+ // then do not sign app image, otherwise use --mac-signing-key-user-name
+ if (INSTALLER_SIGN_IDENTITY.getIsDefaultValue(params)) {
+ // --mac-sign and/or --mac-signing-key-user-name case
+ signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
+ }
+ }
if (signingIdentity != null) {
signAppBundle(params, root, signingIdentity,
BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params),
ENTITLEMENTS.fetchFrom(params));
+ } else {
+ // Case when user requested to sign installer only
+ signAppBundle(params, root, "-", null, null);
}
restoreKeychainList(params);
} else if (OperatingSystem.isMacOS()) {
@@ -715,6 +733,25 @@ private static List getCodesignArgs(
return args;
}
+ private static void runCodesign(ProcessBuilder pb, boolean quiet)
+ throws IOException {
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos)) {
+ try {
+ IOUtils.exec(pb, false, ps, false,
+ Executor.INFINITE_TIMEOUT, quiet);
+ } catch (IOException ioe) {
+ // Log output of "codesign" in case of
+ // error. It should help user to diagnose
+ // issue when using --mac-app-image-sign-identity
+ Log.info(MessageFormat.format(I18N.getString(
+ "error.tool.failed.with.output"), "codesign"));
+ Log.info(baos.toString().strip());
+ throw ioe;
+ }
+ }
+ }
+
static void signAppBundle(
Map params, Path appLocation,
String signingIdentity, String identifierPrefix, Path entitlements)
@@ -781,8 +818,7 @@ static void signAppBundle(
p.toFile().setWritable(true, true);
ProcessBuilder pb = new ProcessBuilder(args);
// run quietly
- IOUtils.exec(pb, false, null, false,
- Executor.INFINITE_TIMEOUT, true);
+ runCodesign(pb, true);
Files.setPosixFilePermissions(p, oldPermissions);
} catch (IOException ioe) {
toThrow.set(ioe);
@@ -810,8 +846,7 @@ static void signAppBundle(
List args = getCodesignArgs(true, path, signingIdentity,
identifierPrefix, entitlements, keyChain);
ProcessBuilder pb = new ProcessBuilder(args);
-
- IOUtils.exec(pb);
+ runCodesign(pb, false);
} catch (IOException e) {
toThrow.set(e);
}
@@ -842,8 +877,7 @@ static void signAppBundle(
List args = getCodesignArgs(true, appLocation, signingIdentity,
identifierPrefix, entitlements, keyChain);
ProcessBuilder pb = new ProcessBuilder(args);
-
- IOUtils.exec(pb);
+ runCodesign(pb, false);
}
private static String extractBundleIdentifier(Map params) {
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
index b4f63d66f5722..8d9db0a007783 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
@@ -79,6 +79,13 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
params -> "",
null);
+ public static final BundlerParamInfo INSTALLER_SIGN_IDENTITY =
+ new StandardBundlerParam<>(
+ Arguments.CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getId(),
+ String.class,
+ params -> "",
+ null);
+
public static final BundlerParamInfo MAC_INSTALLER_NAME =
new StandardBundlerParam<> (
"mac.installerName",
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
index 60cd11b6f06f8..6ac84975451b4 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
@@ -28,7 +28,9 @@
import jdk.internal.util.Architecture;
import jdk.internal.util.OSVersion;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
@@ -54,6 +56,8 @@
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
+import static jdk.jpackage.internal.MacBaseInstallerBundler.INSTALLER_SIGN_IDENTITY;
+import static jdk.jpackage.internal.MacAppBundler.APP_IMAGE_SIGN_IDENTITY;
import static jdk.jpackage.internal.StandardBundlerParam.APP_STORE;
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
import static jdk.jpackage.internal.OverridableResource.createResource;
@@ -605,8 +609,19 @@ private Path createPKG(Map params,
Log.verbose(I18N.getString("message.signing.pkg"));
}
- String signingIdentity =
- DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
+ String signingIdentity = null;
+ // --mac-installer-sign-identity
+ if (!INSTALLER_SIGN_IDENTITY.getIsDefaultValue(params)) {
+ signingIdentity = INSTALLER_SIGN_IDENTITY.fetchFrom(params);
+ } else {
+ // Use --mac-signing-key-user-name if user did not request
+ // to sign just app image using --mac-app-image-sign-identity
+ if (APP_IMAGE_SIGN_IDENTITY.getIsDefaultValue(params)) {
+ // --mac-signing-key-user-name
+ signingIdentity = DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
+ }
+ }
+
if (signingIdentity != null) {
commandLine.add("--sign");
commandLine.add(signingIdentity);
@@ -638,7 +653,21 @@ private Path createPKG(Map params,
commandLine.add(finalPKG.toAbsolutePath().toString());
pb = new ProcessBuilder(commandLine);
- IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
+
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos)) {
+ try {
+ IOUtils.exec(pb, false, ps, true, Executor.INFINITE_TIMEOUT);
+ } catch (IOException ioe) {
+ // Log output of "productbuild" in case of
+ // error. It should help user to diagnose
+ // issue when using --mac-installer-sign-identity
+ Log.info(MessageFormat.format(I18N.getString(
+ "error.tool.failed.with.output"), "productbuild"));
+ Log.info(baos.toString().strip());
+ throw ioe;
+ }
+ }
return finalPKG;
} catch (Exception ignored) {
@@ -702,14 +731,19 @@ public boolean validate(Map params)
// reject explicitly set sign to true and no valid signature key
if (Optional.ofNullable(
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
- String signingIdentity =
- DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
- if (signingIdentity == null) {
- throw new ConfigException(
- I18N.getString("error.explicit-sign-no-cert"),
- I18N.getString(
- "error.explicit-sign-no-cert.advice"));
+ if (!SIGNING_KEY_USER.getIsDefaultValue(params)) {
+ String signingIdentity =
+ DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
+ if (signingIdentity == null) {
+ throw new ConfigException(
+ I18N.getString("error.explicit-sign-no-cert"),
+ I18N.getString(
+ "error.explicit-sign-no-cert.advice"));
+ }
}
+
+ // No need to validate --mac-installer-sign-identity, since it is
+ // pass through option.
}
// hdiutil is always available so there's no need
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
index c575df2494e02..de4e7157b2ae3 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2023, 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
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Install Xcode with command line developer tools.
error.cert.not.found=No certificate found matching [{0}] using keychain [{1}]
error.multiple.certs.found=WARNING: Multiple certificates found matching [{0}] using keychain [{1}], using first one
error.app-image.mac-sign.required=Error: --mac-sign option is required with predefined application image and with type [app-image]
+error.tool.failed.with.output=Error: "{0}" failed with following output:
resource.bundle-config-file=Bundle config file
resource.app-info-plist=Application Info.plist
resource.runtime-info-plist=Java Runtime Info.plist
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
index 6dd037c9bce05..8586041d417f9 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2023, 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
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Installieren Sie Xcode mit Befehlszeilen-Entwickle
error.cert.not.found=Kein Zertifikat gefunden, das [{0}] mit Schlüsselbund [{1}] entspricht
error.multiple.certs.found=WARNUNG: Mehrere Zertifikate gefunden, die [{0}] mit Schlüsselbund [{1}] entsprechen. Es wird das erste Zertifikat verwendet
error.app-image.mac-sign.required=Fehler: Die Option "--mac-sign" ist mit einem vordefinierten Anwendungsimage und Typ [app-image] erforderlich
+error.tool.failed.with.output=Error: "{0}" failed with following output:
resource.bundle-config-file=Bundle-Konfigurationsdatei
resource.app-info-plist=Info.plist der Anwendung
resource.runtime-info-plist=Info.plist von Java Runtime
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
index b75d1dc465f36..518e3e45f97e9 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2023, 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
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Xcodeとコマンドライン・デベロッパ・
error.cert.not.found=キーチェーン[{1}]を使用する[{0}]と一致する証明書が見つかりません
error.multiple.certs.found=警告: キーチェーン[{1}]を使用する[{0}]と一致する複数の証明書が見つかりました。最初のものを使用します
error.app-image.mac-sign.required=エラー: --mac-signオプションは、事前定義済アプリケーション・イメージおよびタイプ[app-image]で必要です
+error.tool.failed.with.output=Error: "{0}" failed with following output:
resource.bundle-config-file=バンドル構成ファイル
resource.app-info-plist=アプリケーションのInfo.plist
resource.runtime-info-plist=JavaランタイムのInfo.plist
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
index dc1f592852dd9..c4e4bd2293950 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2023, 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
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=安装带命令行开发人员工具的 Xcode。
error.cert.not.found=使用密钥链 [{1}] 找不到与 [{0}] 匹配的证书
error.multiple.certs.found=警告:使用密钥链 [{1}] 找到多个与 [{0}] 匹配的证书,将使用第一个证书
error.app-image.mac-sign.required=错误:预定义的应用程序映像和类型 [app image] 需要 --mac-sign 选项
+error.tool.failed.with.output=Error: "{0}" failed with following output:
resource.bundle-config-file=包配置文件
resource.app-info-plist=应用程序 Info.plist
resource.runtime-info-plist=Java 运行时 Info.plist
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java
index b4a28e7fb3c4e..16cd89d9d52d0 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java
@@ -338,6 +338,12 @@ public enum CLIOptions {
MAC_SIGNING_KEY_NAME ("mac-signing-key-user-name",
OptionCategories.PLATFORM_MAC),
+ MAC_APP_IMAGE_SIGN_IDENTITY ("mac-app-image-sign-identity",
+ OptionCategories.PLATFORM_MAC),
+
+ MAC_INSTALLER_SIGN_IDENTITY ("mac-installer-sign-identity",
+ OptionCategories.PLATFORM_MAC),
+
MAC_SIGNING_KEYCHAIN ("mac-signing-keychain",
OptionCategories.PLATFORM_MAC),
@@ -631,6 +637,24 @@ private void validateArguments() throws PackagerException {
CLIOptions.JLINK_OPTIONS.getIdWithPrefix());
}
}
+ if (allOptions.contains(CLIOptions.MAC_SIGNING_KEY_NAME) &&
+ allOptions.contains(CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY)) {
+ throw new PackagerException("ERR_MutuallyExclusiveOptions",
+ CLIOptions.MAC_SIGNING_KEY_NAME.getIdWithPrefix(),
+ CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY.getIdWithPrefix());
+ }
+ if (allOptions.contains(CLIOptions.MAC_SIGNING_KEY_NAME) &&
+ allOptions.contains(CLIOptions.MAC_INSTALLER_SIGN_IDENTITY)) {
+ throw new PackagerException("ERR_MutuallyExclusiveOptions",
+ CLIOptions.MAC_SIGNING_KEY_NAME.getIdWithPrefix(),
+ CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getIdWithPrefix());
+ }
+ if (isMac && (imageOnly || "dmg".equals(type)) &&
+ allOptions.contains(CLIOptions.MAC_INSTALLER_SIGN_IDENTITY)) {
+ throw new PackagerException("ERR_InvalidTypeOption",
+ CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getIdWithPrefix(),
+ type);
+ }
if (allOptions.contains(CLIOptions.DMG_CONTENT)
&& !("dmg".equals(type))) {
throw new PackagerException("ERR_InvalidTypeOption",
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java
index 4173980002bb8..fa99073ff7f79 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,11 +46,6 @@ class BundlerParamInfo {
*/
Class valueType;
- /**
- * Indicates if value was set using default value function
- */
- boolean isDefaultValue;
-
/**
* If the value is not set, and no fallback value is found,
* the parameter uses the value returned by the producer.
@@ -70,8 +65,24 @@ Class getValueType() {
return valueType;
}
- boolean getIsDefaultValue() {
- return isDefaultValue;
+ /**
+ * Returns true if value was not provided on command line for this
+ * parameter.
+ *
+ * @param params - params from which value will be fetch
+ * @return true if value was not provided on command line, false otherwise
+ */
+ boolean getIsDefaultValue(Map params) {
+ Object o = params.get(getID());
+ if (o != null) {
+ return false; // We have user provided value
+ }
+
+ if (params.containsKey(getID())) {
+ return false; // explicit nulls are allowed for provided value
+ }
+
+ return true;
}
Function