From 5a31ab28206bf31d5b0f94aa2c075525350e6653 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 29 Jun 2023 10:57:43 +0000 Subject: [PATCH 01/15] 8311007: jdk/jfr/tool/TestView.java can't find event Reviewed-by: mgronlun Backport-of: e3f18af1dfca1be292a76ed209a7e4ca75ca94da --- test/jdk/jdk/jfr/jcmd/TestJcmdView.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdView.java b/test/jdk/jdk/jfr/jcmd/TestJcmdView.java index f6857b759a8..29bf1c22743 100644 --- a/test/jdk/jdk/jfr/jcmd/TestJcmdView.java +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdView.java @@ -23,9 +23,11 @@ package jdk.jfr.jcmd; +import java.time.Instant; import java.util.concurrent.CountDownLatch; import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingStream; import jdk.test.lib.process.OutputAnalyzer; /** @@ -40,6 +42,7 @@ * -XX:+UseG1GC jdk.jfr.jcmd.TestJcmdView */ public class TestJcmdView { + private static volatile Instant lastTimestamp; public static void main(String... args) throws Throwable { CountDownLatch jvmInformation = new CountDownLatch(1); @@ -60,22 +63,27 @@ public static void main(String... args) throws Throwable { rs.onEvent("jdk.JVMInformation", e -> { jvmInformation.countDown(); System.out.println(e); + storeLastTimestamp(e); }); rs.onEvent("jdk.SystemGC", e -> { systemGC.countDown(); System.out.println(e); + storeLastTimestamp(e); }); rs.onEvent("jdk.GCHeapSummary", e -> { gcHeapSummary.countDown(); System.out.println(e); + storeLastTimestamp(e); }); rs.onEvent("jdk.OldGarbageCollection", e -> { oldCollection.countDown(); System.out.println(e); + storeLastTimestamp(e); }); rs.onEvent("jdk.GarbageCollection", e-> { garbageCollection.countDown(); System.out.println(e); + storeLastTimestamp(e); }); rs.startAsync(); // Emit some GC events @@ -87,6 +95,16 @@ public static void main(String... args) throws Throwable { systemGC.await(); gcHeapSummary.await(); oldCollection.countDown(); + // Wait for Instant.now() to advance 1 s past the last event timestamp. + // The rationale for this is twofold: + // - DcmdView starts one second before Instant.now() (to make the command + // responsive for the user). + // - Instant.now() and the event timestamp use different time sources + // and they need to synchronize. + Instant end = lastTimestamp.plusSeconds(1); + while (Instant.now().isBefore(end)) { + Thread.sleep(10); + } // Test events that are in the current chunk testEventType(); testFormView(); @@ -101,6 +119,13 @@ public static void main(String... args) throws Throwable { } } + private static void storeLastTimestamp(RecordedEvent e) { + Instant time = e.getEndTime(); + if (lastTimestamp == null || time.isAfter(lastTimestamp)) { + lastTimestamp = time; + } + } + private static void rotate() { try (Recording r = new Recording()) { r.start(); From 91598a94f20128e65e31a57273d7952bbf9cae7b Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 29 Jun 2023 13:01:02 +0000 Subject: [PATCH 02/15] 8310299: C2: 8275201 broke constant folding of array store check in some cases Reviewed-by: chagedorn Backport-of: be64d3ac3cf9da2658038d64233f080da8011dc8 --- src/hotspot/share/opto/memnode.cpp | 2 +- .../c2/irTests/TestArrayElementTypeLoad.java | 58 +++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 5 ++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestArrayElementTypeLoad.java diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 505b8cab05f..286f901bd5d 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2378,7 +2378,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const { // The array's TypeKlassPtr was declared 'precise' or 'not precise' // according to the element type's subclassing. - return tkls->is_aryklassptr()->elem(); + return tkls->is_aryklassptr()->elem()->isa_klassptr()->cast_to_exactness(tkls->klass_is_exact()); } if (tkls->isa_instklassptr() != nullptr && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::super_offset())) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestArrayElementTypeLoad.java b/test/hotspot/jtreg/compiler/c2/irTests/TestArrayElementTypeLoad.java new file mode 100644 index 00000000000..e867c257e1f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestArrayElementTypeLoad.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. 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 compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @library /test/lib / + * @run driver compiler.c2.irTests.TestArrayElementTypeLoad + */ + +public class TestArrayElementTypeLoad { + public static void main(String[] args) { + TestFramework.run(); + } + + static final A[] array = new A[1]; + + @Test + @IR(phase = { CompilePhase.ITER_GVN1 }, failOn = { IRNode.SUBTYPE_CHECK }) + public static void test1(A a) { + array[0] = a; + } + + @Run(test = "test1") + private void test1Runner() { + test1(new A()); + test1(new B()); + } + + static class A { + } + + static class B extends A { + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 2422d96cdd6..955ecd5b475 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1188,6 +1188,11 @@ public class IRNode { beforeMatchingNameRegex(SUB_V, "SubV(B|S|I|L|F|D)"); } + public static final String SUBTYPE_CHECK = PREFIX + "SUBTYPE_CHECK" + POSTFIX; + static { + beforeMatchingNameRegex(SUBTYPE_CHECK, "SubTypeCheck"); + } + public static final String TRAP = PREFIX + "TRAP" + POSTFIX; static { trapNodes(TRAP,"reason"); From 60db329e4cd2a9fe7f7f23e0ddde3356bab8ba51 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 29 Jun 2023 20:52:42 +0000 Subject: [PATCH 03/15] 8311115: Type in java.lang.reflect.AccessFlag.METHOD_PARAMETER Reviewed-by: prappo Backport-of: d97966266e343671693825d2211a34fa45dd271d --- src/java.base/share/classes/java/lang/reflect/AccessFlag.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java index 92178085d65..92c6655552e 100644 --- a/src/java.base/share/classes/java/lang/reflect/AccessFlag.java +++ b/src/java.base/share/classes/java/lang/reflect/AccessFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -539,7 +539,7 @@ public enum Location { INNER_CLASS, /** - * Method parameter loccation. + * Method parameter location. * @jvms 4.7.24. The MethodParameters Attribute */ METHOD_PARAMETER, From 3210d32088abf0e1e27d9fcfdd3d6beebf309136 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 30 Jun 2023 10:26:14 +0000 Subject: [PATCH 04/15] 8309902: C2: assert(false) failed: Bad graph detected in build_loop_late after JDK-8305189 Reviewed-by: chagedorn Backport-of: 26efff758684b9c5615fb3b087538d713e6eca10 --- src/hotspot/share/opto/loopTransform.cpp | 6 -- .../loopopts/TestAssertPredicatePeeling.java | 58 +++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestAssertPredicatePeeling.java diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 775299eb0c2..7c3f5841f3f 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2043,12 +2043,6 @@ bool IdealLoopTree::is_invariant(Node* n) const { // to the new stride. void PhaseIdealLoop::update_main_loop_assertion_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, const int stride_con) { - if (init->Opcode() == Op_CastII) { - // skip over the cast added by PhaseIdealLoop::cast_incr_before_loop() when pre/post/main loops are created because - // it can get in the way of type propagation - assert(((CastIINode*)init)->carry_dependency() && loop_head->skip_predicates() == init->in(0), "casted iv phi from pre loop expected"); - init = init->in(1); - } Node* entry = ctrl; Node* prev_proj = ctrl; LoopNode* outer_loop_head = loop_head->skip_strip_mined(); diff --git a/test/hotspot/jtreg/compiler/loopopts/TestAssertPredicatePeeling.java b/test/hotspot/jtreg/compiler/loopopts/TestAssertPredicatePeeling.java new file mode 100644 index 00000000000..31daf9c5089 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestAssertPredicatePeeling.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. 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 8309902 + * @summary C2: assert(false) failed: Bad graph detected in build_loop_late after JDK-8305189 + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestAssertPredicatePeeling::* TestAssertPredicatePeeling + */ + + +public class TestAssertPredicatePeeling { + static volatile long instanceCount; + + public static void main(String[] strArr) { + test(); + } + + static int test() { + int i2 = 2, i17 = 3, i18 = 2, iArr[] = new int[10]; + + int i15 = 1; + while (i15 < 100000) { + for (int i16 = i15; i16 < 1; ++i16) { + try { + iArr[i16] = 5 / iArr[6]; + i17 = iArr[5] / i2; + i2 = i15; + } catch (ArithmeticException a_e) { + } + instanceCount -= i15; + } + i15++; + } + return i17; + } +} + From 6d2f34fcff24493e03354386dffbe1cb45fe6352 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Fri, 30 Jun 2023 13:16:03 +0000 Subject: [PATCH 05/15] 8311046: ProblemList gc/z/TestHighUsage.java with Generational ZGC Reviewed-by: stefank Backport-of: 2a9e2f614f367965cb106ce42d865161e056c386 --- test/hotspot/jtreg/ProblemList-generational-zgc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList-generational-zgc.txt b/test/hotspot/jtreg/ProblemList-generational-zgc.txt index f61022418bb..7981c2cc976 100644 --- a/test/hotspot/jtreg/ProblemList-generational-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-generational-zgc.txt @@ -116,4 +116,4 @@ vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows- vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all vmTestbase/nsk/sysdict/vm/stress/chain/chain007/chain007.java 8298991 linux-x64 -gc/z/TestHighUsage.java 8308843 windows-x64 +gc/z/TestHighUsage.java 8308843 generic-all From 35d592e39d2bc99543d1b6bf671fc73fbef35bc8 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 30 Jun 2023 22:34:06 +0000 Subject: [PATCH 06/15] 8311186: ProblemList javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java on linux-aarch64 8311189: disable gc/z/TestHighUsage.java 8311190: ProblemList javax/management/remote/mandatory/connection/DeadLockTest.java with virtual threads on windows-x64 8311191: ProblemList javax/management/remote/mandatory/connection/ConnectionTest.java with virtual threads on windows-x64 8311193: ProblemList vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java on linux-all 8311195: ProblemList vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java with Xcomp on macosx-x64 Reviewed-by: lmesnik Backport-of: 140b70fb29e2b83e5d33765906ee76a36442a687 --- test/hotspot/jtreg/ProblemList-Xcomp.txt | 2 ++ test/hotspot/jtreg/ProblemList-generational-zgc.txt | 2 -- test/hotspot/jtreg/ProblemList.txt | 2 ++ test/hotspot/jtreg/gc/z/TestHighUsage.java | 1 + test/jdk/ProblemList-Virtual.txt | 4 ++++ test/jdk/ProblemList.txt | 2 ++ 6 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index f29ee2e8c5b..6780e5a5b58 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -46,3 +46,5 @@ serviceability/sa/ClhsdbInspect.java 8283578 windows-x64 vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8308367 windows-x64 vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_a/TestDescription.java 8308367 windows-x64 vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInTarget/TestDescription.java 8308367 windows-x64 + +vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 8299493 macosx-x64 diff --git a/test/hotspot/jtreg/ProblemList-generational-zgc.txt b/test/hotspot/jtreg/ProblemList-generational-zgc.txt index 7981c2cc976..de22024f8d7 100644 --- a/test/hotspot/jtreg/ProblemList-generational-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-generational-zgc.txt @@ -115,5 +115,3 @@ vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows- vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all vmTestbase/nsk/sysdict/vm/stress/chain/chain007/chain007.java 8298991 linux-x64 - -gc/z/TestHighUsage.java 8308843 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index ba3553375f9..d5e82ecc571 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -173,3 +173,5 @@ vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64 + +vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java 8310551 linux-all diff --git a/test/hotspot/jtreg/gc/z/TestHighUsage.java b/test/hotspot/jtreg/gc/z/TestHighUsage.java index d2c07aaa9ab..5d92c3fba55 100644 --- a/test/hotspot/jtreg/gc/z/TestHighUsage.java +++ b/test/hotspot/jtreg/gc/z/TestHighUsage.java @@ -28,6 +28,7 @@ * @requires vm.gc.ZGenerational * @summary Test ZGC "High Usage" rule * @library /test/lib + * @ignore 8308843 * @run main/othervm gc.z.TestHighUsage */ diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index 5796651cd6d..d30e52d061f 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -48,6 +48,10 @@ java/lang/ScopedValue/StressStackOverflow.java 8309646 generic-all java/lang/instrument/NativeMethodPrefixAgent.java 8307169 generic-all +javax/management/remote/mandatory/connection/DeadLockTest.java 8309069 windows-x64 + +javax/management/remote/mandatory/connection/ConnectionTest.java 8308352 windows-x64 + ########## ## Tests incompatible with virtual test thread factory. ## There is no goal to run all test with virtual test thread factory. diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 6987ea5967c..1af30f0e294 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -523,6 +523,8 @@ javax/management/remote/mandatory/connection/RMIConnector_NPETest.java 8267887 g javax/management/remote/mandatory/connection/BrokenConnectionTest.java 8262312 linux-all +javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java 8149084 linux-aarch64 + ############################################################################ # jdk_net From bbcabe4200da92f932a541e143a4adb337fddba0 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Sat, 1 Jul 2023 02:44:03 +0000 Subject: [PATCH 07/15] 8310838: Correct range notations in MethodTypeDesc specification Reviewed-by: mchung Backport-of: a197ee797b3580d9f85636522587d3f6418dff6a --- .../share/classes/java/lang/constant/MethodTypeDesc.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java index ea0c3a93764..ff750ccc893 100644 --- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java +++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java @@ -119,7 +119,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) { * @param index the index of the parameter to retrieve * @return a {@link ClassDesc} describing the desired parameter type * @throws IndexOutOfBoundsException if the index is outside the half-open - * range {[0, parameterCount())} + * range {@code [0, parameterCount())} */ ClassDesc parameterType(int index); @@ -156,7 +156,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) { * @return a {@linkplain MethodTypeDesc} describing the desired method type * @throws NullPointerException if any argument is {@code null} * @throws IndexOutOfBoundsException if the index is outside the half-open - * range {[0, parameterCount)} + * range {@code [0, parameterCount)} */ MethodTypeDesc changeParameterType(int index, ClassDesc paramType); @@ -183,7 +183,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) { * @return a {@linkplain MethodTypeDesc} describing the desired method type * @throws NullPointerException if any argument or its contents are {@code null} * @throws IndexOutOfBoundsException if {@code pos} is outside the closed - * range {[0, parameterCount]} + * range {@code [0, parameterCount]} * @throws IllegalArgumentException if any element of {@code paramTypes} * is a {@link ClassDesc} for {@code void} */ From 8088bc4033884adbd249ae9eb92c3ad1b81a69da Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Sat, 1 Jul 2023 02:44:28 +0000 Subject: [PATCH 08/15] 8309819: Clarify API note in Class::getName and MethodType::toMethodDescriptorString Reviewed-by: mchung Backport-of: 8c8e9d911d388f6ee621ed4d322efc56a9876708 --- .../share/classes/java/lang/Class.java | 24 ++++----- .../classes/java/lang/invoke/MethodType.java | 50 ++++++++++--------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index c036f7400b9..ddc5a55f0b2 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -170,7 +170,7 @@ * may be hidden interfaces. * * The {@linkplain #getName() name of a hidden class or interface} is - * not a binary name, + * not a {@linkplain ClassLoader##binary-name binary name}, * which means the following: *
    *
  • A hidden class or interface cannot be referenced by the constant pools @@ -542,8 +542,8 @@ private static native Class forName0(String name, boolean initialize, /** - * Returns the {@code Class} with the given - * binary name in the given module. + * Returns the {@code Class} with the given {@linkplain ClassLoader##binary-name + * binary name} in the given module. * *

    This method attempts to locate and load the class or interface. * It does not link the class, and does not run the class initializer. @@ -566,7 +566,7 @@ private static native Class forName0(String name, boolean initialize, * loads a class in another module. * * @param module A module - * @param name The binary name + * @param name The {@linkplain ClassLoader##binary-name binary name} * of the class * @return {@code Class} object of the given name defined in the given module; * {@code null} if not found. @@ -884,11 +884,11 @@ public boolean isSynthetic() { * not an array class, then: *

      *
    • If the class or interface is not {@linkplain #isHidden() hidden}, - * then the binary name + * then the {@linkplain ClassLoader##binary-name binary name} * of the class or interface is returned. *
    • If the class or interface is hidden, then the result is a string * of the form: {@code N + '/' + } - * where {@code N} is the binary name + * where {@code N} is the {@linkplain ClassLoader##binary-name binary name} * indicated by the {@code class} file passed to * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) * Lookup::defineHiddenClass}, and {@code } is an unqualified name. @@ -908,7 +908,7 @@ public boolean isSynthetic() { * {@code boolean} {@code Z} * {@code byte} {@code B} * {@code char} {@code C} - * class or interface with binary name N + * class or interface with {@linkplain ClassLoader##binary-name binary name} N * {@code L}N{@code ;} * {@code double} {@code D} * {@code float} {@code F} @@ -936,6 +936,9 @@ public boolean isSynthetic() { * returns "[[[[[[[I" * * + * @apiNote + * Distinct class objects can have the same name but different class loaders. + * * @return the name of the class, interface, or other entity * represented by this {@code Class} object. * @jls 13.1 The Form of a Binary @@ -4526,7 +4529,7 @@ public Class[] getNestMembers() { *
      * {@code "L" +} N {@code + "." + + ";"} *
      - * where N is the binary name + * where N is the {@linkplain ClassLoader##binary-name binary name} * encoded in internal form indicated by the {@code class} file passed to * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) * Lookup::defineHiddenClass}, and {@code } is an unqualified name. @@ -4554,11 +4557,6 @@ public Class[] getNestMembers() { * is a one-letter code corresponding to a primitive type or {@code void} * ({@code "B", "C", "D", "F", "I", "J", "S", "Z", "V"}) (JVMS {@jvms 4.3.2}). * - * @apiNote - * This is not a strict inverse of {@link #forName}; - * distinct classes which share a common name but have different class loaders - * will have identical descriptor strings. - * * @return the descriptor string for this {@code Class} object * @jvms 4.3.2 Field Descriptors * @since 12 diff --git a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java index 4c4f546725a..951d209b69f 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -51,7 +51,6 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; -import static java.lang.invoke.MethodType.fromDescriptor; /** * A method type represents the arguments and return type accepted and @@ -1161,26 +1160,29 @@ Invokers invokers() { } /** - * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor. - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. + * Finds or creates an instance of a method type of the given method descriptor + * (JVMS {@jvms 4.3.3}). This method is a convenience method for + * {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Any class or interface name embedded in the descriptor string will be - * resolved by the given loader (or if it is null, on the system class loader). - *

      - * Note that it is possible to encounter method types which cannot be - * constructed by this method, because their component types are - * not all reachable from a common class loader. + * resolved by the given loader (or if it is {@code null}, on the system class loader). + * + * @apiNote + * It is possible to encounter method types that have valid descriptors but + * cannot be constructed by this method, because their component types are + * not visible from a common class loader. *

      * This method is included for the benefit of applications that must * generate bytecodes that process method handles and {@code invokedynamic}. - * @param descriptor a bytecode-level type descriptor string "(T...)T" + * @param descriptor a method descriptor string * @param loader the class loader in which to look up the types - * @return a method type matching the bytecode-level type descriptor - * @throws NullPointerException if the string is null - * @throws IllegalArgumentException if the string is not well-formed + * @return a method type of the given method descriptor + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string is not a method descriptor * @throws TypeNotPresentException if a named type cannot be found * @throws SecurityException if the security manager is present and * {@code loader} is {@code null} and the caller does not have the * {@link RuntimePermission}{@code ("getClassLoader")} + * @jvms 4.3.3 Method Descriptors */ public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader) throws IllegalArgumentException, TypeNotPresentException @@ -1220,19 +1222,20 @@ static MethodType fromDescriptor(String descriptor, ClassLoader loader) } /** - * Returns a descriptor string for the method type. This method + * {@return the descriptor string for this method type} This method * is equivalent to calling {@link #descriptorString() MethodType::descriptorString}. * - *

      - * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}. - * Two distinct classes which share a common name but have different class loaders - * will appear identical when viewed within descriptor strings. + * @apiNote + * This is not a strict inverse of {@link #fromMethodDescriptorString + * fromMethodDescriptorString} which requires a method type descriptor + * (JVMS {@jvms 4.3.3}) and a suitable class loader argument. + * Two distinct {@code MethodType} objects can have an identical + * descriptor string as distinct classes can have the same name + * but different class loaders. + * *

      * This method is included for the benefit of applications that must * generate bytecodes that process method handles and {@code invokedynamic}. - * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString}, - * because the latter requires a suitable class loader argument. - * @return the descriptor string for this method type * @jvms 4.3.3 Method Descriptors * @see Nominal Descriptor for {@code MethodType} */ @@ -1246,16 +1249,16 @@ public String toMethodDescriptorString() { } /** - * Returns a descriptor string for this method type. + * {@return the descriptor string for this method type} * *

      - * If this method type can be described nominally, + * If this method type can be {@linkplain ##descriptor described nominally}, * then the result is a method type descriptor (JVMS {@jvms 4.3.3}). * {@link MethodTypeDesc MethodTypeDesc} for this method type * can be produced by calling {@link MethodTypeDesc#ofDescriptor(String) * MethodTypeDesc::ofDescriptor} with the result descriptor string. *

      - * If this method type cannot be described nominally + * If this method type cannot be {@linkplain ##descriptor described nominally} * and the result is a string of the form: *

      {@code "()"}
      * where {@code } is the concatenation of the @@ -1264,7 +1267,6 @@ public String toMethodDescriptorString() { * of the return type. No {@link java.lang.constant.MethodTypeDesc MethodTypeDesc} * can be produced from the result string. * - * @return the descriptor string for this method type * @since 12 * @jvms 4.3.3 Method Descriptors * @see Nominal Descriptor for {@code MethodType} From 6f3f4aa2936f5cbe120da1e29e924bc99cfd27d1 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 3 Jul 2023 06:58:57 +0000 Subject: [PATCH 09/15] 8310380: Handle problems in core-related tests on macOS when codesign tool does not work Reviewed-by: cjplummer Backport-of: 39c104df44f17c1d65e35becd4272f73e2c6610c --- .../sa/TestJmapCoreMetaspace.java | 4 +- ...stMutuallyExclusivePlatformPredicates.java | 4 +- test/lib/jdk/test/lib/Platform.java | 46 +++++++++++++------ test/lib/jdk/test/lib/util/CoreUtils.java | 9 +++- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java index 3dd060be231..b8e00e53848 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,7 @@ /** * @test TestJmapCoreMetaspace - * @summary Test verifies that jhsdb jmap could generate heap dump from core when metspace is full + * @summary Test verifies that jhsdb jmap could generate heap dump from core when metaspace is full * @requires vm.hasSA * @library /test/lib * @run driver/timeout=480 TestJmapCore run metaspace diff --git a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java index 045be5361d7..355cd8ac200 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, 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 @@ -53,7 +53,7 @@ private static enum MethodGroup { IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isMusl", "isSlowDebugBuild", "hasSA", "isRoot", "isTieredSupported", "areCustomLoadersSupportedForCDS", "isDefaultCDSArchiveSupported", - "isHardenedOSX"); + "isHardenedOSX", "hasOSXPlistEntries"); public final List methodNames; diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 647c62834aa..c58877c6c5e 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -260,28 +260,46 @@ public static boolean hasSA() { return true; } - /** - * Return true if the test JDK is hardened, otherwise false. Only valid on OSX. - */ - public static boolean isHardenedOSX() throws IOException { - // We only care about hardened binaries for 10.14 and later (actually 10.14.5, but - // for simplicity we'll also include earlier 10.14 versions). - if (getOsVersionMajor() == 10 && getOsVersionMinor() < 14) { - return false; // assume not hardened - } - - // Find the path to the java binary. + private static Process launchCodesignOnJavaBinary() throws IOException { String jdkPath = System.getProperty("java.home"); Path javaPath = Paths.get(jdkPath + "/bin/java"); String javaFileName = javaPath.toAbsolutePath().toString(); if (Files.notExists(javaPath)) { throw new FileNotFoundException("Could not find file " + javaFileName); } - - // Run codesign on the java binary. ProcessBuilder pb = new ProcessBuilder("codesign", "--display", "--verbose", javaFileName); pb.redirectErrorStream(true); // redirect stderr to stdout Process codesignProcess = pb.start(); + return codesignProcess; + } + + public static boolean hasOSXPlistEntries() throws IOException { + Process codesignProcess = launchCodesignOnJavaBinary(); + BufferedReader is = new BufferedReader(new InputStreamReader(codesignProcess.getInputStream())); + String line; + while ((line = is.readLine()) != null) { + System.out.println("STDOUT: " + line); + if (line.indexOf("Info.plist=not bound") != -1) { + return false; + } + if (line.indexOf("Info.plist entries=") != -1) { + return true; + } + } + System.out.println("No matching Info.plist entry was found"); + return false; + } + + /** + * Return true if the test JDK is hardened, otherwise false. Only valid on OSX. + */ + public static boolean isHardenedOSX() throws IOException { + // We only care about hardened binaries for 10.14 and later (actually 10.14.5, but + // for simplicity we'll also include earlier 10.14 versions). + if (getOsVersionMajor() == 10 && getOsVersionMinor() < 14) { + return false; // assume not hardened + } + Process codesignProcess = launchCodesignOnJavaBinary(); BufferedReader is = new BufferedReader(new InputStreamReader(codesignProcess.getInputStream())); String line; boolean isHardened = false; diff --git a/test/lib/jdk/test/lib/util/CoreUtils.java b/test/lib/jdk/test/lib/util/CoreUtils.java index f69ef5ce08e..f7a486def2b 100644 --- a/test/lib/jdk/test/lib/util/CoreUtils.java +++ b/test/lib/jdk/test/lib/util/CoreUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -127,6 +127,8 @@ public static String getCoreFileLocation(String crashOutputString, long pid) thr } return coreFileLocation; // success! + } else { + System.out.println("Core file not found. Trying to find a reason why..."); } // See if we can figure out the likely reason the core file was not found. Recover from @@ -148,6 +150,11 @@ public static String getCoreFileLocation(String crashOutputString, long pid) thr // We can't generate cores files with hardened binaries on OSX 10.15 and later. throw new SkippedException("Cannot produce core file with hardened binary on OSX 10.15 and later"); } + } else { + // codesign has to add entitlements using the plist. If this is not present we might not generate a core file. + if (!Platform.hasOSXPlistEntries()) { + throw new SkippedException("Cannot produce core file with binary having no plist entitlement entries"); + } } } else if (Platform.isLinux()) { // Check if a crash report tool is installed. From 6de4e8f601852f9f4b96974dd210ccaf1f655145 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 3 Jul 2023 10:37:40 +0000 Subject: [PATCH 10/15] 8310829: guarantee(!HAS_PENDING_EXCEPTION) failed in ExceptionTranslation::doit Reviewed-by: chagedorn Backport-of: f6bdccb45caca0f69918a773a9ad9b2ad91b702f --- src/hotspot/share/classfile/vmClassMacros.hpp | 2 +- src/hotspot/share/classfile/vmSymbols.hpp | 2 +- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 2 +- src/hotspot/share/jvmci/jvmciEnv.cpp | 85 ++++++++++++------- .../classes/jdk/internal/vm/VMSupport.java | 47 ++++++---- .../internal/vm/TestTranslatedException.java | 70 ++++++++++++++- 6 files changed, 155 insertions(+), 53 deletions(-) diff --git a/src/hotspot/share/classfile/vmClassMacros.hpp b/src/hotspot/share/classfile/vmClassMacros.hpp index 9f86d39c432..bb2babff25a 100644 --- a/src/hotspot/share/classfile/vmClassMacros.hpp +++ b/src/hotspot/share/classfile/vmClassMacros.hpp @@ -31,7 +31,7 @@ #define VM_CLASS_ID(kname) vmClassID::_VM_CLASS_ENUM(kname) // VM_CLASSES_DO iterates the classes that are directly referenced -// by the VM, suhch as java.lang.Object and java.lang.String. These +// by the VM, such as java.lang.Object and java.lang.String. These // classes are resolved at VM bootstrap, before any Java code is executed, // so no class loader is able to provide a different definition. // diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index b344d5ed932..1677597e72b 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -760,7 +760,7 @@ template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(encodeAnnotations_name, "encodeAnnotations") \ template(encodeAnnotations_signature, "([BLjava/lang/Class;Ljdk/internal/reflect/ConstantPool;Z[Ljava/lang/Class;)[B")\ - template(decodeAndThrowThrowable_signature, "(JZ)V") \ + template(decodeAndThrowThrowable_signature, "(IJZ)V") \ template(classRedefinedCount_name, "classRedefinedCount") \ template(classLoader_name, "classLoader") \ template(componentType_name, "componentType") \ diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 247551e1301..9e161892046 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -582,7 +582,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU TempNewSymbol class_name = SymbolTable::new_symbol(str); if (class_name->utf8_length() <= 1) { - JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string())); + JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", str)); } JVMCIKlassHandle resolved_klass(THREAD); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 430b7a59262..32759a1889a 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -446,6 +446,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char** // Shared code for translating an exception from HotSpot to libjvmci or vice versa. class ExceptionTranslation: public StackObj { protected: + enum DecodeFormat { + _encoded_ok = 0, // exception was successfully encoded into buffer + _buffer_alloc_fail = 1, // native memory for buffer could not be allocated + _encode_oome_fail = 2, // OutOfMemoryError thrown during encoding + _encode_fail = 3 // some other problem occured during encoding. If buffer != 0, + // buffer contains a `struct { u4 len; char[len] desc}` + // describing the problem + }; + JVMCIEnv* _from_env; // Source of translation. Can be null. JVMCIEnv* _to_env; // Destination of translation. Never null. @@ -454,49 +463,34 @@ class ExceptionTranslation: public StackObj { // Encodes the exception in `_from_env` into `buffer`. // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size` // and the encoding was written to `buffer` otherwise returns -N. - virtual int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) = 0; + virtual int encode(JavaThread* THREAD, jlong buffer, int buffer_size) = 0; // Decodes the exception in `buffer` in `_to_env` and throws it. - virtual void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) = 0; + virtual void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) = 0; public: void doit(JavaThread* THREAD) { - // Resolve VMSupport class explicitly as HotSpotJVMCI::compute_offsets - // may not have been called. - Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD); - guarantee(!HAS_PENDING_EXCEPTION, ""); - int buffer_size = 2048; while (true) { ResourceMark rm; jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jbyte, buffer_size); if (buffer == 0L) { - decode(THREAD, vmSupport, 0L); + JVMCI_event_1("error translating exception: translation buffer allocation failed"); + decode(THREAD, _buffer_alloc_fail, 0L); return; } - int res = encode(THREAD, vmSupport, buffer, buffer_size); - if (_from_env != nullptr && !_from_env->is_hotspot() && _from_env->has_pending_exception()) { - // Cannot get name of exception thrown by `encode` as that involves - // calling into libjvmci which in turn can raise another exception. - _from_env->clear_pending_exception(); - decode(THREAD, vmSupport, -2L); - return; - } else if (HAS_PENDING_EXCEPTION) { - Symbol *ex_name = PENDING_EXCEPTION->klass()->name(); - CLEAR_PENDING_EXCEPTION; - if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { - decode(THREAD, vmSupport, -1L); - } else { - decode(THREAD, vmSupport, -2L); - } + int res = encode(THREAD, buffer, buffer_size); + if (_to_env->has_pending_exception()) { + // Propagate pending exception return; - } else if (res < 0) { + } + if (res < 0) { int required_buffer_size = -res; if (required_buffer_size > buffer_size) { buffer_size = required_buffer_size; } } else { - decode(THREAD, vmSupport, buffer); + decode(THREAD, _encoded_ok, buffer); if (!_to_env->has_pending_exception()) { _to_env->throw_InternalError("decodeAndThrowThrowable should have thrown an exception"); } @@ -511,7 +505,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { private: const Handle& _throwable; - int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) { + int encode(JavaThread* THREAD, jlong buffer, int buffer_size) { + Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD); + if (HAS_PENDING_EXCEPTION) { + Handle throwable = Handle(THREAD, PENDING_EXCEPTION); + Symbol *ex_name = throwable->klass()->name(); + CLEAR_PENDING_EXCEPTION; + if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { + JVMCI_event_1("error translating exception: OutOfMemoryError"); + decode(THREAD, _encode_oome_fail, 0L); + } else { + char* char_buffer = (char*) buffer + 4; + stringStream st(char_buffer, (size_t) buffer_size - 4); + java_lang_Throwable::print_stack_trace(throwable, &st); + u4 len = (u4) st.size(); + *((u4*) buffer) = len; + JVMCI_event_1("error translating exception: %s", char_buffer); + decode(THREAD, _encode_fail, buffer); + } + return 0; + } JavaCallArguments jargs; jargs.push_oop(_throwable); jargs.push_long(buffer); @@ -524,11 +537,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { return result.get_jint(); } - void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) { + void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) { JNIAccessMark jni(_to_env, THREAD); jni()->CallStaticVoidMethod(JNIJVMCI::VMSupport::clazz(), JNIJVMCI::VMSupport::decodeAndThrowThrowable_method(), - buffer, false); + format, buffer, false); } public: HotSpotToSharedLibraryExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) : @@ -540,15 +553,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation { private: jthrowable _throwable; - int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) { + int encode(JavaThread* THREAD, jlong buffer, int buffer_size) { JNIAccessMark jni(_from_env, THREAD); - return jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(), + int res = jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(), JNIJVMCI::VMSupport::encodeThrowable_method(), _throwable, buffer, buffer_size); + if (jni()->ExceptionCheck()) { + // Cannot get name of exception thrown as that can raise another exception. + jni()->ExceptionClear(); + JVMCI_event_1("error translating exception: unknown error"); + decode(THREAD, _encode_fail, 0L); + return 0; + } + return res; } - void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) { + void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) { + Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, CHECK); JavaCallArguments jargs; + jargs.push_int(format); jargs.push_long(buffer); jargs.push_int(true); JavaValue result(T_VOID); diff --git a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java index 659645a5006..1a5069e53f3 100644 --- a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java @@ -40,6 +40,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.IncompleteAnnotationException; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; @@ -125,36 +126,46 @@ public static byte[] serializeSavedPropertiesToByteArray() throws IOException { public static native String getVMTemporaryDirectory(); /** - * Decodes the exception encoded in {@code errorOrBuffer} and throws it. - * - * @param errorOrBuffer an error code or a native byte errorOrBuffer containing an exception encoded by - * {@link #encodeThrowable}. Error code values and their meanings are: + * Decodes the exception described by {@code format} and {@code buffer} and throws it. * + * @param format specifies how to interpret {@code buffer}: *
      -     *             0: native memory for the errorOrBuffer could not be allocated
      -     *            -1: an OutOfMemoryError was thrown while encoding the exception
      -     *            -2: some other throwable was thrown while encoding the exception
      +     *             0: {@code buffer} was created by {@link #encodeThrowable}
      +     *             1: native memory for {@code buffer} could not be allocated
      +     *             2: an OutOfMemoryError was thrown while encoding the exception
      +     *             3: some other problem occured while encoding the exception. If {@code buffer != 0},
      +     *                it contains a {@code struct { u4 len; char[len] desc}} where {@code desc} describes the problem
            *            
      - * @param errorOrBuffer a native byte errorOrBuffer containing an exception encoded by - * {@link #encodeThrowable} + * @param buffer encoded info about the exception to throw (depends on {@code format}) * @param inJVMHeap [@code true} if executing in the JVM heap, {@code false} otherwise */ - public static void decodeAndThrowThrowable(long errorOrBuffer, boolean inJVMHeap) throws Throwable { - if (errorOrBuffer >= -2L && errorOrBuffer <= 0) { + public static void decodeAndThrowThrowable(int format, long buffer, boolean inJVMHeap) throws Throwable { + if (format != 0) { String context = String.format("while encoding an exception to translate it %s the JVM heap", inJVMHeap ? "to" : "from"); - if (errorOrBuffer == 0) { - throw new InternalError("native errorOrBuffer could not be allocated " + context); + if (format == 1) { + throw new InternalError("native buffer could not be allocated " + context); } - if (errorOrBuffer == -1L) { + if (format == 2) { throw new OutOfMemoryError("OutOfMemoryError occurred " + context); } + if (format == 3 && buffer != 0L) { + byte[] bytes = bufferToBytes(buffer); + throw new InternalError("unexpected problem occurred " + context + ": " + new String(bytes, StandardCharsets.UTF_8)); + } throw new InternalError("unexpected problem occurred " + context); } - int encodingLength = U.getInt(errorOrBuffer); - byte[] encoding = new byte[encodingLength]; - U.copyMemory(null, errorOrBuffer + 4, encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, encodingLength); - throw TranslatedException.decodeThrowable(encoding); + throw TranslatedException.decodeThrowable(bufferToBytes(buffer)); + } + + private static byte[] bufferToBytes(long buffer) { + if (buffer == 0) { + return null; + } + int len = U.getInt(buffer); + byte[] bytes = new byte[len]; + U.copyMemory(null, buffer + 4, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, len); + return bytes; } /** diff --git a/test/jdk/jdk/internal/vm/TestTranslatedException.java b/test/jdk/jdk/internal/vm/TestTranslatedException.java index 335f71ccf3a..6ad6d526bd3 100644 --- a/test/jdk/jdk/internal/vm/TestTranslatedException.java +++ b/test/jdk/jdk/internal/vm/TestTranslatedException.java @@ -34,6 +34,7 @@ import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import org.testng.Assert; import org.testng.annotations.Test; @@ -57,11 +58,78 @@ public void encodeDecodeTest() throws Exception { throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); } encodeDecode(throwable); + + try { + VMSupport.decodeAndThrowThrowable(0, 0L, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (NullPointerException decoded) { + // Expected + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } + + try { + VMSupport.decodeAndThrowThrowable(1, 0L, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (InternalError decoded) { + if (!decoded.getMessage().startsWith("native buffer could not be allocated")) { + throw new AssertionError("unexpected exception: " + decoded); + } + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } + + try { + VMSupport.decodeAndThrowThrowable(2, 0L, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (OutOfMemoryError decoded) { + // Expected + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } + + try { + VMSupport.decodeAndThrowThrowable(3, 0L, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (InternalError decoded) { + // Expected + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } + + try { + VMSupport.decodeAndThrowThrowable(4, 0L, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (InternalError decoded) { + // Expected + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } + + Unsafe unsafe = Unsafe.getUnsafe(); + byte[] problem = "very unlikely problem".getBytes(StandardCharsets.UTF_8); + long buffer = unsafe.allocateMemory(problem.length + 4); + try { + unsafe.putInt(buffer, problem.length); + unsafe.copyMemory(problem, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buffer + 4, problem.length); + VMSupport.decodeAndThrowThrowable(3, buffer, true); + throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); + } catch (InternalError decoded) { + String msg = decoded.getMessage(); + if (!msg.endsWith("very unlikely problem")) { + throw new AssertionError("unexpected exception: " + decoded); + } + } catch (Throwable decoded) { + throw new AssertionError("unexpected exception: " + decoded); + } finally { + unsafe.freeMemory(buffer); + } } private void encodeDecode(Throwable throwable) throws Exception { Unsafe unsafe = Unsafe.getUnsafe(); int bufferSize = 512; + int format = 0; long buffer = 0L; while (true) { buffer = unsafe.allocateMemory(bufferSize); @@ -71,7 +139,7 @@ private void encodeDecode(Throwable throwable) throws Exception { bufferSize = -res; } else { try { - VMSupport.decodeAndThrowThrowable(buffer, true); + VMSupport.decodeAndThrowThrowable(format, buffer, true); throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); } catch (Throwable decoded) { assertThrowableEquals(throwable, decoded); From 205dffe3831a0edca16bb66d9e455c741d543034 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 3 Jul 2023 20:58:14 +0000 Subject: [PATCH 11/15] 8254566: Clarify the spec of ClassLoader::getClassLoadingLock for non-parallel capable loader Reviewed-by: iris Backport-of: b9198f993173b0fbdc7ff1400e2205d3969370da --- .../share/classes/java/lang/ClassLoader.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index 2e3d9e550e7..079a40accde 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -647,11 +647,20 @@ final Class loadClass(Module module, String name) { /** * Returns the lock object for class loading operations. - * For backward compatibility, the default implementation of this method - * behaves as follows. If this ClassLoader object is registered as - * parallel capable, the method returns a dedicated object associated - * with the specified class name. Otherwise, the method returns this - * ClassLoader object. + * + * @implSpec + * If this {@code ClassLoader} object is registered as parallel capable, + * this method returns a dedicated object associated with the specified + * class name. Otherwise, this method returns this {@code ClassLoader} object. + * + * @apiNote + * This method allows parallel capable class loaders to implement + * finer-grained locking schemes such that multiple threads may load classes + * concurrently without deadlocks. For non-parallel-capable class loaders, + * the {@code ClassLoader} object is synchronized on during the class loading + * operations. Class loaders with non-hierarchical delegation should be + * {@linkplain #registerAsParallelCapable() registered as parallel capable} + * to prevent deadlocks. * * @param className * The name of the to-be-loaded class @@ -659,7 +668,7 @@ final Class loadClass(Module module, String name) { * @return the lock for class loading operations * * @throws NullPointerException - * If registered as parallel capable and {@code className} is null + * If registered as parallel capable and {@code className} is {@code null} * * @see #loadClass(String, boolean) * From 8d6ef6fd5bedadee4afac66f3bd3b9213e72d5f5 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 4 Jul 2023 07:43:12 +0000 Subject: [PATCH 12/15] 8310549: avoid potential leaks in KeystoreImpl.m related to JNU_CHECK_EXCEPTION early returns Reviewed-by: clanger Backport-of: 7da3f1999fc5d1b9162443d97dfae7fe7b04dfc5 --- src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m index b4e19a27995..b4f13a80d96 100644 --- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m +++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m @@ -363,7 +363,9 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore) // Call back to the Java object to create Java objects corresponding to this security object. jlong nativeKeyRef = ptr_to_jlong(privateKeyRef); (*env)->CallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray); - JNU_CHECK_EXCEPTION(env); + if ((*env)->ExceptionCheck(env)) { + goto errOut; + } } } while (searchResult == noErr); @@ -505,7 +507,9 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) // Call back to the Java object to create Java objects corresponding to this security object. jlong nativeRef = ptr_to_jlong(certRef); (*env)->CallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, inputTrust, nativeRef, creationDate, certData); - JNU_CHECK_EXCEPTION(env); + if ((*env)->ExceptionCheck(env)) { + goto errOut; + } } } while (searchResult == noErr); From c9111d57ce132d70d4360535254658ef6b8d134d Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 4 Jul 2023 12:45:35 +0000 Subject: [PATCH 13/15] 8310743: assert(reserved_rgn != nullptr) failed: Add committed region, No reserved region found Reviewed-by: ayang Backport-of: f393975d1b9423835a7aa42f6ffc0656499701d7 --- src/hotspot/share/gc/z/zGlobals.hpp | 3 + src/hotspot/share/gc/z/zMemory.cpp | 4 + src/hotspot/share/gc/z/zMemory.hpp | 2 + src/hotspot/share/gc/z/zNMT.cpp | 121 ++++++++++++++++++ src/hotspot/share/gc/z/zNMT.hpp | 53 ++++++++ src/hotspot/share/gc/z/zPhysicalMemory.cpp | 26 +--- src/hotspot/share/gc/z/zPhysicalMemory.hpp | 3 - src/hotspot/share/gc/z/zVirtualMemory.cpp | 86 ++++++++++--- src/hotspot/share/gc/z/zVirtualMemory.hpp | 5 +- src/hotspot/share/gc/z/z_globals.hpp | 15 ++- ...stZForceDiscontiguousHeapReservations.java | 70 ++++++++++ test/hotspot/jtreg/gc/z/TestZNMT.java | 105 +++++++++++++++ 12 files changed, 445 insertions(+), 48 deletions(-) create mode 100644 src/hotspot/share/gc/z/zNMT.cpp create mode 100644 src/hotspot/share/gc/z/zNMT.hpp create mode 100644 test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java create mode 100644 test/hotspot/jtreg/gc/z/TestZNMT.java diff --git a/src/hotspot/share/gc/z/zGlobals.hpp b/src/hotspot/share/gc/z/zGlobals.hpp index 0ca08942080..f7c0a3eaa26 100644 --- a/src/hotspot/share/gc/z/zGlobals.hpp +++ b/src/hotspot/share/gc/z/zGlobals.hpp @@ -38,6 +38,9 @@ const size_t ZGranuleSize = (size_t)1 << ZGranuleSizeShift // Virtual memory to physical memory ratio const size_t ZVirtualToPhysicalRatio = 16; // 16:1 +// Max virtual memory ranges +const size_t ZMaxVirtualReservations = 100; // Each reservation at least 1% of total + // Page size shifts const size_t ZPageSizeSmallShift = ZGranuleSizeShift; extern size_t ZPageSizeMediumShift; diff --git a/src/hotspot/share/gc/z/zMemory.cpp b/src/hotspot/share/gc/z/zMemory.cpp index d665d1181b0..7bc6b7379c5 100644 --- a/src/hotspot/share/gc/z/zMemory.cpp +++ b/src/hotspot/share/gc/z/zMemory.cpp @@ -81,6 +81,10 @@ ZMemoryManager::ZMemoryManager() : _freelist(), _callbacks() {} +bool ZMemoryManager::free_is_contiguous() const { + return _freelist.size() == 1; +} + void ZMemoryManager::register_callbacks(const Callbacks& callbacks) { _callbacks = callbacks; } diff --git a/src/hotspot/share/gc/z/zMemory.hpp b/src/hotspot/share/gc/z/zMemory.hpp index e75ac071d1d..ce9100f8026 100644 --- a/src/hotspot/share/gc/z/zMemory.hpp +++ b/src/hotspot/share/gc/z/zMemory.hpp @@ -81,6 +81,8 @@ class ZMemoryManager { public: ZMemoryManager(); + bool free_is_contiguous() const; + void register_callbacks(const Callbacks& callbacks); zoffset peek_low_address() const; diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp new file mode 100644 index 00000000000..d8753dc2283 --- /dev/null +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#include "precompiled.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zNMT.hpp" +#include "gc/z/zVirtualMemory.hpp" +#include "memory/allocation.hpp" +#include "services/memTracker.hpp" +#include "utilities/nativeCallStack.hpp" + +ZNMT::Reservation ZNMT::_reservations[ZMaxVirtualReservations] = {}; +size_t ZNMT::_num_reservations = 0; + +size_t ZNMT::reservation_index(zoffset offset, size_t* offset_in_reservation) { + assert(_num_reservations > 0, "at least one reservation must exist"); + + size_t index = 0; + *offset_in_reservation = untype(offset); + for (; index < _num_reservations; ++index) { + const size_t reservation_size = _reservations[index]._size; + if (*offset_in_reservation < reservation_size) { + break; + } + *offset_in_reservation -= reservation_size; + } + + assert(index != _num_reservations, "failed to find reservation index"); + return index; +} + +void ZNMT::process_fake_mapping(zoffset offset, size_t size, bool commit) { + // In order to satisfy NTM's requirement of an 1:1 mapping between committed + // and reserved addresses, a fake mapping from the offset into the reservation + // is used. + // + // These mappings from + // [offset, offset + size) -> {[virtual address range], ...} + // are stable after the heap has been reserved. No commits proceed any + // reservations. Committing and uncommitting the same [offset, offset + size) + // range will result in same virtual memory ranges. + + size_t left_to_process = size; + size_t offset_in_reservation; + for (size_t i = reservation_index(offset, &offset_in_reservation); i < _num_reservations; ++i) { + const zaddress_unsafe reservation_start = _reservations[i]._start; + const size_t reservation_size = _reservations[i]._size; + const size_t sub_range_size = MIN2(left_to_process, reservation_size - offset_in_reservation); + const uintptr_t sub_range_addr = untype(reservation_start) + offset_in_reservation; + + // commit / uncommit memory + if (commit) { + MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC); + } else { + if (MemTracker::enabled()) { + Tracker tracker(Tracker::uncommit); + tracker.record((address)sub_range_addr, sub_range_size); + } + } + + left_to_process -= sub_range_size; + if (left_to_process == 0) { + // Processed all nmt registrations + return; + } + + offset_in_reservation = 0; + } + + assert(left_to_process == 0, "everything was not commited"); +} + +void ZNMT::reserve(zaddress_unsafe start, size_t size) { + assert(_num_reservations < ZMaxVirtualReservations, "too many reservations"); + // Keep track of the reservations made in order to create fake mappings + // between the reserved and commited memory. + // See details in ZNMT::process_fake_mapping + _reservations[_num_reservations++] = {start, size}; + + MemTracker::record_virtual_memory_reserve((void*)untype(start), size, CALLER_PC, mtJavaHeap); +} + +void ZNMT::commit(zoffset offset, size_t size) { + // NMT expects a 1-to-1 mapping between virtual and physical memory. + // ZGC can temporarily have multiple virtual addresses pointing to + // the same physical memory. + // + // When this function is called we don't know where in the virtual memory + // this physical memory will be mapped. So we fake the virtual memory + // address by mapping the physical offset into offsets in the reserved + // memory space. + process_fake_mapping(offset, size, true); +} + +void ZNMT::uncommit(zoffset offset, size_t size) { + // We fake the virtual memory address by mapping the physical offset + // into offsets in the reserved memory space. + // See comment in ZNMT::commit + process_fake_mapping(offset, size, false); +} diff --git a/src/hotspot/share/gc/z/zNMT.hpp b/src/hotspot/share/gc/z/zNMT.hpp new file mode 100644 index 00000000000..118f8654ade --- /dev/null +++ b/src/hotspot/share/gc/z/zNMT.hpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef SHARE_GC_Z_ZNMT_HPP +#define SHARE_GC_Z_ZNMT_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zMemory.hpp" +#include "gc/z/zVirtualMemory.hpp" +#include "memory/allStatic.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/nativeCallStack.hpp" + +class ZNMT : public AllStatic { +private: + struct Reservation { + zaddress_unsafe _start; + size_t _size; + }; + static Reservation _reservations[ZMaxVirtualReservations]; + static size_t _num_reservations; + + static size_t reservation_index(zoffset offset, size_t* offset_in_reservation); + static void process_fake_mapping(zoffset offset, size_t size, bool commit); + +public: + static void reserve(zaddress_unsafe start, size_t size); + static void commit(zoffset offset, size_t size); + static void uncommit(zoffset offset, size_t size); +}; + +#endif // SHARE_GC_Z_ZNMT_HPP diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp index 7631708df86..c0e0e837c9c 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp @@ -27,6 +27,7 @@ #include "gc/z/zArray.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zLargePages.inline.hpp" +#include "gc/z/zNMT.hpp" #include "gc/z/zNUMA.inline.hpp" #include "gc/z/zPhysicalMemory.inline.hpp" #include "logging/log.hpp" @@ -34,7 +35,6 @@ #include "runtime/globals_extension.hpp" #include "runtime/init.hpp" #include "runtime/os.hpp" -#include "services/memTracker.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" @@ -275,26 +275,6 @@ void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max log_info_p(gc, init)("Uncommit Delay: " UINTX_FORMAT "s", ZUncommitDelay); } -void ZPhysicalMemoryManager::nmt_commit(zoffset offset, size_t size) const { - // NMT expects a 1-to-1 mapping between virtual and physical memory. - // ZGC can temporarily have multiple virtual addresses pointing to - // the same physical memory. - // - // When this function is called we don't know where in the virtual memory - // this physical memory will be mapped. So we fake that the virtual memory - // address is the heap base + the given offset. - const uintptr_t addr = ZAddressHeapBase + untype(offset); - MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC); -} - -void ZPhysicalMemoryManager::nmt_uncommit(zoffset offset, size_t size) const { - if (MemTracker::enabled()) { - const uintptr_t addr = ZAddressHeapBase + untype(offset); - Tracker tracker(Tracker::uncommit); - tracker.record((address)addr, size); - } -} - void ZPhysicalMemoryManager::alloc(ZPhysicalMemory& pmem, size_t size) { assert(is_aligned(size, ZGranuleSize), "Invalid size"); @@ -329,7 +309,7 @@ bool ZPhysicalMemoryManager::commit(ZPhysicalMemory& pmem) { const size_t committed = _backing.commit(segment.start(), segment.size()); // Register with NMT - nmt_commit(segment.start(), committed); + ZNMT::commit(segment.start(), committed); // Register committed segment if (!pmem.commit_segment(i, committed)) { @@ -355,7 +335,7 @@ bool ZPhysicalMemoryManager::uncommit(ZPhysicalMemory& pmem) { const size_t uncommitted = _backing.uncommit(segment.start(), segment.size()); // Unregister with NMT - nmt_uncommit(segment.start(), uncommitted); + ZNMT::uncommit(segment.start(), uncommitted); // Deregister uncommitted segment if (!pmem.uncommit_segment(i, uncommitted)) { diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.hpp b/src/hotspot/share/gc/z/zPhysicalMemory.hpp index 0cf77dad739..2244732a146 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp @@ -84,9 +84,6 @@ class ZPhysicalMemoryManager { ZPhysicalMemoryBacking _backing; ZMemoryManager _manager; - void nmt_commit(zoffset offset, size_t size) const; - void nmt_uncommit(zoffset offset, size_t size) const; - void pretouch_view(zaddress addr, size_t size) const; void map_view(zaddress_unsafe addr, const ZPhysicalMemory& pmem) const; void unmap_view(zaddress_unsafe addr, size_t size) const; diff --git a/src/hotspot/share/gc/z/zVirtualMemory.cpp b/src/hotspot/share/gc/z/zVirtualMemory.cpp index 37eb42ddb12..6b53b2ba7c8 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.cpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.cpp @@ -22,12 +22,13 @@ */ #include "precompiled.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zAddress.inline.hpp" #include "gc/z/zAddressSpaceLimit.hpp" #include "gc/z/zGlobals.hpp" +#include "gc/z/zNMT.hpp" #include "gc/z/zVirtualMemory.inline.hpp" -#include "services/memTracker.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" @@ -54,6 +55,39 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) _initialized = true; } +#ifdef ASSERT +size_t ZVirtualMemoryManager::force_reserve_discontiguous(size_t size) { + const size_t min_range = calculate_min_range(size); + const size_t max_range = MAX2(align_down(size / ZForceDiscontiguousHeapReservations, ZGranuleSize), min_range); + size_t reserved = 0; + + // Try to reserve ZForceDiscontiguousHeapReservations number of virtual memory + // ranges. Starting with higher addresses. + uintptr_t end = ZAddressOffsetMax; + while (reserved < size && end >= max_range) { + const size_t remaining = size - reserved; + const size_t reserve_size = MIN2(max_range, remaining); + const uintptr_t reserve_start = end - reserve_size; + + if (reserve_contiguous(to_zoffset(reserve_start), reserve_size)) { + reserved += reserve_size; + } + + end -= reserve_size * 2; + } + + // If (reserved < size) attempt to reserve the rest via normal divide and conquer + uintptr_t start = 0; + while (reserved < size && start < ZAddressOffsetMax) { + const size_t remaining = MIN2(size - reserved, ZAddressOffsetMax - start); + reserved += reserve_discontiguous(to_zoffset(start), remaining, min_range); + start += remaining; + } + + return reserved; +} +#endif + size_t ZVirtualMemoryManager::reserve_discontiguous(zoffset start, size_t size, size_t min_range) { if (size < min_range) { // Too small @@ -75,15 +109,20 @@ size_t ZVirtualMemoryManager::reserve_discontiguous(zoffset start, size_t size, // Divide and conquer const size_t first_part = align_down(half, ZGranuleSize); const size_t second_part = size - first_part; - return reserve_discontiguous(start, first_part, min_range) + - reserve_discontiguous(start + first_part, second_part, min_range); + const size_t first_size = reserve_discontiguous(start, first_part, min_range); + const size_t second_size = reserve_discontiguous(start + first_part, second_part, min_range); + return first_size + second_size; } -size_t ZVirtualMemoryManager::reserve_discontiguous(size_t size) { +size_t ZVirtualMemoryManager::calculate_min_range(size_t size) { // Don't try to reserve address ranges smaller than 1% of the requested size. // This avoids an explosion of reservation attempts in case large parts of the // address space is already occupied. - const size_t min_range = align_up(size / 100, ZGranuleSize); + return align_up(size / ZMaxVirtualReservations, ZGranuleSize); +} + +size_t ZVirtualMemoryManager::reserve_discontiguous(size_t size) { + const size_t min_range = calculate_min_range(size); uintptr_t start = 0; size_t reserved = 0; @@ -98,7 +137,7 @@ size_t ZVirtualMemoryManager::reserve_discontiguous(size_t size) { } bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) { - assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned " SIZE_FORMAT_X, size); // Reserve address views const zaddress_unsafe addr = ZOffset::address_unsafe(start); @@ -109,7 +148,7 @@ bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) { } // Register address views with native memory tracker - nmt_reserve(addr, size); + ZNMT::reserve(addr, size); // Make the address range free _manager.free(start, size); @@ -137,15 +176,25 @@ bool ZVirtualMemoryManager::reserve(size_t max_capacity) { const size_t limit = MIN2(ZAddressOffsetMax, ZAddressSpaceLimit::heap()); const size_t size = MIN2(max_capacity * ZVirtualToPhysicalRatio, limit); - size_t reserved = size; - bool contiguous = true; + auto do_reserve = [&]() { +#ifdef ASSERT + if (ZForceDiscontiguousHeapReservations > 0) { + return force_reserve_discontiguous(size); + } +#endif + + // Prefer a contiguous address space + if (reserve_contiguous(size)) { + return size; + } - // Prefer a contiguous address space - if (!reserve_contiguous(size)) { // Fall back to a discontiguous address space - reserved = reserve_discontiguous(size); - contiguous = false; - } + return reserve_discontiguous(size); + }; + + const size_t reserved = do_reserve(); + + const bool contiguous = _manager.free_is_contiguous(); log_info_p(gc, init)("Address Space Type: %s/%s/%s", (contiguous ? "Contiguous" : "Discontiguous"), @@ -159,11 +208,6 @@ bool ZVirtualMemoryManager::reserve(size_t max_capacity) { return reserved >= max_capacity; } -void ZVirtualMemoryManager::nmt_reserve(zaddress_unsafe start, size_t size) { - MemTracker::record_virtual_memory_reserve((void*)untype(start), size, CALLER_PC); - MemTracker::record_virtual_memory_type((void*)untype(start), mtJavaHeap); -} - bool ZVirtualMemoryManager::is_initialized() const { return _initialized; } @@ -179,6 +223,10 @@ ZVirtualMemory ZVirtualMemoryManager::alloc(size_t size, bool force_low_address) start = _manager.alloc_high_address(size); } + if (start == zoffset(UINTPTR_MAX)) { + return ZVirtualMemory(); + } + return ZVirtualMemory(start, size); } diff --git a/src/hotspot/share/gc/z/zVirtualMemory.hpp b/src/hotspot/share/gc/z/zVirtualMemory.hpp index 153cad81be4..faf7cdc6216 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.hpp @@ -24,6 +24,7 @@ #ifndef SHARE_GC_Z_ZVIRTUALMEMORY_HPP #define SHARE_GC_Z_ZVIRTUALMEMORY_HPP +#include "gc/z/zAddress.hpp" #include "gc/z/zMemory.hpp" class ZVirtualMemory { @@ -47,6 +48,8 @@ class ZVirtualMemory { class ZVirtualMemoryManager { private: + static size_t calculate_min_range(size_t size); + ZMemoryManager _manager; size_t _reserved; bool _initialized; @@ -63,7 +66,7 @@ class ZVirtualMemoryManager { size_t reserve_discontiguous(size_t size); bool reserve(size_t max_capacity); - void nmt_reserve(zaddress_unsafe start, size_t size); + DEBUG_ONLY(size_t force_reserve_discontiguous(size_t size);) public: ZVirtualMemoryManager(size_t max_capacity); diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index 1ff63ca9c6c..01fb0e0a91f 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -24,7 +24,8 @@ #ifndef SHARE_GC_Z_Z_GLOBALS_HPP #define SHARE_GC_Z_Z_GLOBALS_HPP -#include "zPageAge.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zPageAge.hpp" #define GC_Z_FLAGS(develop, \ develop_pd, \ @@ -68,7 +69,17 @@ \ product(int, ZTenuringThreshold, -1, DIAGNOSTIC, \ "Young generation tenuring threshold, -1 for dynamic computation")\ - range(-1, static_cast(ZPageAgeMax)) + range(-1, static_cast(ZPageAgeMax)) \ + \ + develop(size_t, ZForceDiscontiguousHeapReservations, 0, \ + "The gc will attempt to split the heap reservation into this " \ + "many reservations, subject to available virtual address space " \ + "and invariant restrictions. Higher virtual addresses are " \ + "preferred " \ + "0: Disabled " \ + "1: Attempt contiguous reservation starting at a higher address " \ + "N: Force that many reservations, if possible") \ + range(0, ZMaxVirtualReservations) // end of GC_Z_FLAGS diff --git a/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java b/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java new file mode 100644 index 00000000000..18b37c21442 --- /dev/null +++ b/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package gc.z; + +/** + * @test TestZForceDiscontiguousHeapReservations + * @requires vm.gc.ZGenerational & vm.debug + * @summary Test the ZForceDiscontiguousHeapReservations development flag + * @library /test/lib + * @run driver gc.z.TestZForceDiscontiguousHeapReservations + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestZForceDiscontiguousHeapReservations { + + private static void testValue(int n) throws Exception { + /** + * Xmx is picked so that it is divisible by 'ZForceDiscontiguousHeapReservations * ZGranuleSize' + * Xms is picked so that it is less than '16 * Xmx / ZForceDiscontiguousHeapReservations' as ZGC + * cannot currently handle a discontiguous heap with an initial size larger than the individual + * reservations. + */ + final int XmxInM = 2000; + final int XmsInM = Math.min(16 * XmxInM / (n + 1), XmxInM); + OutputAnalyzer oa = ProcessTools.executeProcess(ProcessTools.createTestJvm( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xms" + XmsInM + "M", + "-Xmx" + XmxInM + "M", + "-Xlog:gc,gc+init", + "-XX:ZForceDiscontiguousHeapReservations=" + n, + "-version")) + .outputTo(System.out) + .errorTo(System.out) + .shouldHaveExitValue(0); + if (n > 1) { + oa.shouldContain("Address Space Type: Discontiguous"); + } + } + + public static void main(String[] args) throws Exception { + testValue(0); + testValue(1); + testValue(2); + testValue(100); + } +} diff --git a/test/hotspot/jtreg/gc/z/TestZNMT.java b/test/hotspot/jtreg/gc/z/TestZNMT.java new file mode 100644 index 00000000000..87a8643fcd5 --- /dev/null +++ b/test/hotspot/jtreg/gc/z/TestZNMT.java @@ -0,0 +1,105 @@ +/* + * 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. + */ + +package gc.z; + +/** + * @test TestZNMT + * @bug 8310743 + * @requires vm.gc.ZGenerational & vm.debug + * @summary Test NMT and ZGenerational heap reservation / commits interactions. + * @library / /test/lib + * @run driver gc.z.TestZNMT + */ + +import static gc.testlibrary.Allocation.blackHole; +import java.util.ArrayList; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestZNMT { + private static final int XmxInM = 2000; + static class Test { + private static final int K = 1024; + private static final int M = K * K; + public static void main(String[] args) throws Exception { + final int zForceDiscontiguousHeapReservations = Integer.parseInt(args[0]); + final int XmsInM = Integer.parseInt(args[1]); + // 75% of the largest allocation that fits within one reservation + // (or Xmx / zForceDiscontiguousHeapReservations), whichever is smallest + final int allocationInM = (int)(Math.min(zForceDiscontiguousHeapReservations == 0 + ? XmxInM + : XmxInM / zForceDiscontiguousHeapReservations, + XmsInM) * 0.75); + ArrayList list = new ArrayList<>(zForceDiscontiguousHeapReservations); + for (int i = 0; i < zForceDiscontiguousHeapReservations; i++) { + list.add(new byte[allocationInM * M]); + } + blackHole(list); + } + } + + + private static void testValue(int zForceDiscontiguousHeapReservations) throws Exception { + /** + * Xmx is picked so that it is divisible by 'ZForceDiscontiguousHeapReservations * ZGranuleSize' + * Xms is picked so that it is less than '16 * Xmx / ZForceDiscontiguousHeapReservations' as ZGC + * cannot currently handle a discontiguous heap with an initial size larger than the individual + * reservations. + */ + final int XmsInM = Math.min(16 * XmxInM / (zForceDiscontiguousHeapReservations + 1), XmxInM); + OutputAnalyzer oa = ProcessTools.executeProcess(ProcessTools.createTestJvm( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xms" + XmsInM + "M", + "-Xmx" + XmxInM + "M", + "-Xlog:gc,gc+init", + "-XX:ZForceDiscontiguousHeapReservations=" + zForceDiscontiguousHeapReservations, + "-XX:NativeMemoryTracking=detail", + "-XX:+PrintNMTStatistics", + Test.class.getName(), + Integer.toString(zForceDiscontiguousHeapReservations), + Integer.toString(XmxInM))) + .outputTo(System.out) + .errorTo(System.out) + .shouldHaveExitValue(0); + if (zForceDiscontiguousHeapReservations > 1) { + oa.shouldContain("Address Space Type: Discontiguous"); + } + + if (XmsInM < XmxInM) { + // There will be reservations which are smaller than the total + // memory allocated in TestZNMT.Test.main. This means that some + // reservation will be completely committed and print the following + // in the NMT statistics. + oa.shouldMatch("reserved and committed \\d+ for Java Heap"); + } + } + + public static void main(String[] args) throws Exception { + testValue(0); + testValue(1); + testValue(2); + testValue(100); + } +} From 604e03de78a0ed4f687ee2cd95b0d409b4c3736a Mon Sep 17 00:00:00 2001 From: Rajan Halade Date: Wed, 5 Jul 2023 17:47:20 +0000 Subject: [PATCH 14/15] 8301379: Verify TLS_ECDH_* cipher suites cannot be negotiated Reviewed-by: mullan Backport-of: 9f64a64376c677dbe1358807329b42737ac78ad9 --- .../ssl/ciphersuites/DisabledAlgorithms.java | 246 ++++++++---------- .../TLSWontNegotiateDisabledCipherAlgos.java | 146 +++++++++++ 2 files changed, 260 insertions(+), 132 deletions(-) create mode 100644 test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index 4f0d4de210c..994169a7182 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -25,6 +25,7 @@ * @test * @bug 8076221 8211883 8163327 8279164 * @summary Check if weak cipher suites are disabled + * @library /javax/net/ssl/templates * @modules jdk.crypto.ec * @run main/othervm DisabledAlgorithms default * @run main/othervm DisabledAlgorithms empty @@ -35,7 +36,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; @@ -45,82 +45,86 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +/* + * This test verifies that setEnabledProtocols() does not override the + * jdk.tls.disabledAlgorithms property. Both the client and server throw + * an exception when creating a handshake context. + * + * In the TLSWontNegotiateDisabledCipherAlgoos test, one side of the connection + * disables the cipher suites and the other side enables them and verifies + * that the handshake cannot complete successfully. + */ public class DisabledAlgorithms { - private static final String pathToStores = "../etc"; - private static final String keyStoreFile = "keystore"; - private static final String trustStoreFile = "truststore"; - private static final String passwd = "passphrase"; - - private static final String keyFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + keyStoreFile; - - private static final String trustFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + trustStoreFile; + public static final SSLContextTemplate.Cert[] CERTIFICATES = { + SSLContextTemplate.Cert.EE_DSA_SHA1_1024, + SSLContextTemplate.Cert.EE_DSA_SHA224_1024, + SSLContextTemplate.Cert.EE_DSA_SHA256_1024, + SSLContextTemplate.Cert.CA_ECDSA_SECP256R1, + SSLContextTemplate.Cert.CA_RSA_2048 + }; // disabled 3DES, DES, RC4, NULL, anon, and ECDH cipher suites - private static final String[] disabled_ciphersuites - = new String[] { - "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", - "TLS_ECDHE_RSA_WITH_RC4_128_SHA", - "SSL_RSA_WITH_RC4_128_SHA", - "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", - "TLS_ECDH_RSA_WITH_RC4_128_SHA", - "SSL_RSA_WITH_RC4_128_MD5", - "TLS_ECDH_anon_WITH_RC4_128_SHA", - "SSL_DH_anon_WITH_RC4_128_MD5", - "SSL_RSA_WITH_NULL_MD5", - "SSL_RSA_WITH_NULL_SHA", - "TLS_RSA_WITH_NULL_SHA256", - "TLS_ECDH_ECDSA_WITH_NULL_SHA", - "TLS_ECDHE_ECDSA_WITH_NULL_SHA", - "TLS_ECDH_RSA_WITH_NULL_SHA", - "TLS_ECDHE_RSA_WITH_NULL_SHA", - "TLS_ECDH_anon_WITH_NULL_SHA", - "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", - "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", - "SSL_DH_anon_WITH_DES_CBC_SHA", - "SSL_DH_anon_WITH_RC4_128_MD5", - "TLS_DH_anon_WITH_AES_128_CBC_SHA", - "TLS_DH_anon_WITH_AES_128_CBC_SHA256", - "TLS_DH_anon_WITH_AES_128_GCM_SHA256", - "TLS_DH_anon_WITH_AES_256_CBC_SHA", - "TLS_DH_anon_WITH_AES_256_CBC_SHA256", - "TLS_DH_anon_WITH_AES_256_GCM_SHA384", - "SSL_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_DSS_WITH_DES_CBC_SHA", - "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", - "SSL_RSA_EXPORT_WITH_RC4_40_MD5", - "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", - "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", - "TLS_ECDH_anon_WITH_NULL_SHA", - "TLS_ECDH_anon_WITH_RC4_128_SHA", - "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", - "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", - "SSL_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" + public static final String[] DISABLED_CIPHERSUITES + = new String[]{ + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDHE_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_SHA", + "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDH_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", + "SSL_RSA_WITH_NULL_MD5", + "SSL_RSA_WITH_NULL_SHA", + "TLS_RSA_WITH_NULL_SHA256", + "TLS_ECDH_ECDSA_WITH_NULL_SHA", + "TLS_ECDHE_ECDSA_WITH_NULL_SHA", + "TLS_ECDH_RSA_WITH_NULL_SHA", + "TLS_ECDHE_RSA_WITH_NULL_SHA", + "TLS_ECDH_anon_WITH_NULL_SHA", + "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", + "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", + "SSL_DH_anon_WITH_DES_CBC_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", + "TLS_DH_anon_WITH_AES_128_CBC_SHA", + "TLS_DH_anon_WITH_AES_128_CBC_SHA256", + "TLS_DH_anon_WITH_AES_128_GCM_SHA256", + "TLS_DH_anon_WITH_AES_256_CBC_SHA", + "TLS_DH_anon_WITH_AES_256_CBC_SHA256", + "TLS_DH_anon_WITH_AES_256_GCM_SHA384", + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", + "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", + "TLS_ECDH_anon_WITH_NULL_SHA", + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" }; public static void main(String[] args) throws Exception { @@ -128,11 +132,6 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("No parameters specified"); } - 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); - switch (args[0]) { case "default": // use default jdk.tls.disabledAlgorithms @@ -140,7 +139,7 @@ public static void main(String[] args) throws Exception { + Security.getProperty("jdk.tls.disabledAlgorithms")); // check that disabled cipher suites can't be used by default - checkFailure(disabled_ciphersuites); + checkFailure(DISABLED_CIPHERSUITES); break; case "empty": // reset jdk.tls.disabledAlgorithms @@ -152,11 +151,11 @@ public static void main(String[] args) throws Exception { // bit key which violates the default certpath constraints. Security.setProperty("jdk.certpath.disabledAlgorithms", ""); System.out.println("jdk.certpath.disabledAlgorithms = " - + Security.getProperty("jdk.certpath.disabledAlgorithms")); + + Security.getProperty("jdk.certpath.disabledAlgorithms")); // check that disabled cipher suites can be used if // jdk.{tls,certpath}.disabledAlgorithms is empty - checkSuccess(disabled_ciphersuites); + checkSuccess(DISABLED_CIPHERSUITES); break; default: throw new RuntimeException("Wrong parameter: " + args[0]); @@ -169,7 +168,7 @@ public static void main(String[] args) throws Exception { * Checks if that specified cipher suites cannot be used. */ private static void checkFailure(String[] ciphersuites) throws Exception { - try (SSLServer server = SSLServer.init(ciphersuites)) { + try (SSLServer server = new SSLServer(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -177,7 +176,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = SSLClient.init(port, ciphersuite)) { + try (SSLClient client = new SSLClient(port, ciphersuite)) { client.connect(); throw new RuntimeException("Expected SSLHandshakeException " + "not thrown"); @@ -204,7 +203,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { * Checks if specified cipher suites can be used. */ private static void checkSuccess(String[] ciphersuites) throws Exception { - try (SSLServer server = SSLServer.init(ciphersuites)) { + try (SSLServer server = new SSLServer(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -212,7 +211,7 @@ private static void checkSuccess(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = SSLClient.init(port, ciphersuite)) { + try (SSLClient client = new SSLClient(port, ciphersuite)) { client.connect(); String negotiated = client.getNegotiatedCipherSuite(); System.out.println("Negotiated cipher suite: " @@ -251,7 +250,8 @@ private static void sleep() { } } - static class SSLServer implements Runnable, AutoCloseable { + static class SSLServer extends SSLContextTemplate implements Runnable, AutoCloseable { + private final SSLServerSocket ssocket; private volatile boolean stopped = false; @@ -259,7 +259,19 @@ static class SSLServer implements Runnable, AutoCloseable { private volatile boolean sslError = false; private volatile boolean otherError = false; - private SSLServer(SSLServerSocket ssocket) { + private SSLServer(String[] ciphersuites) throws Exception { + SSLContext context = createSSLContext(null, + DisabledAlgorithms.CERTIFICATES, getServerContextParameters()); + SSLServerSocketFactory ssf = context.getServerSocketFactory(); + SSLServerSocket ssocket = (SSLServerSocket) + ssf.createServerSocket(0); + + if (ciphersuites != null) { + System.out.println("Server: enable cipher suites: " + + java.util.Arrays.toString(ciphersuites)); + ssocket.setEnabledCipherSuites(ciphersuites); + } + this.ssocket = ssocket; } @@ -293,8 +305,8 @@ public void run() { } else { System.out.println("Server: run: " + e); System.out.println("The exception above occurred " - + "because socket was closed, " - + "please ignore it"); + + "because socket was closed, " + + "please ignore it"); } } } @@ -339,29 +351,23 @@ void stop() { public void close() { stop(); } - - static SSLServer init(String[] ciphersuites) - throws IOException { - SSLServerSocketFactory ssf = (SSLServerSocketFactory) - SSLServerSocketFactory.getDefault(); - SSLServerSocket ssocket = (SSLServerSocket) - ssf.createServerSocket(0); - - if (ciphersuites != null) { - System.out.println("Server: enable cipher suites: " - + java.util.Arrays.toString(ciphersuites)); - ssocket.setEnabledCipherSuites(ciphersuites); - } - - return new SSLServer(ssocket); - } } - static class SSLClient implements AutoCloseable { + static class SSLClient extends SSLContextTemplate implements AutoCloseable { private final SSLSocket socket; - private SSLClient(SSLSocket socket) { + private SSLClient(int port, String ciphersuite) throws Exception { + SSLContext context = createSSLContext(DisabledAlgorithms.CERTIFICATES, + null, getClientContextParameters()); + SSLSocketFactory ssf = context.getSocketFactory(); + SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); + + if (ciphersuite != null) { + System.out.println("Client: enable cipher suite: " + + ciphersuite); + socket.setEnabledCipherSuites(new String[]{ciphersuite}); + } this.socket = socket; } @@ -401,29 +407,5 @@ public void close() throws Exception { } } } - - static SSLClient init(int port) - throws NoSuchAlgorithmException, IOException { - return init(port, null); - } - - static SSLClient init(int port, String ciphersuite) - throws NoSuchAlgorithmException, IOException { - SSLContext context = SSLContext.getDefault(); - SSLSocketFactory ssf = (SSLSocketFactory) - context.getSocketFactory(); - SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); - - if (ciphersuite != null) { - System.out.println("Client: enable cipher suite: " - + ciphersuite); - socket.setEnabledCipherSuites(new String[] { ciphersuite }); - } - - return new SSLClient(socket); - } - } - - } diff --git a/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java b/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java new file mode 100644 index 00000000000..b120f33da94 --- /dev/null +++ b/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java @@ -0,0 +1,146 @@ +/* + * 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. + */ + +import javax.net.ssl.*; +import java.io.IOException; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.security.Security; +import java.util.List; + +/* + * @test id=Server + * @bug 8301379 + * @summary Verify that Java will not negotiate disabled cipher suites when the + * other side of the connection requests them. + * + * @library /javax/net/ssl/templates + * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server true + */ + +/* + * @test id=Client + * @bug 8301379 + * @summary Verify that Java will not negotiate disabled cipher suites when the + * other side of the connection requests them. + * + * @library /javax/net/ssl/templates + * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server false + */ + + +public class TLSWontNegotiateDisabledCipherAlgos { + + public static void main(String [] args) throws Exception { + boolean useDisabledAlgo = Boolean.parseBoolean(args[1]); + if (useDisabledAlgo) { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + + if (args[0].equals("server")) { + try (TLSServer server = new TLSServer(useDisabledAlgo)) { + List command = List.of( + Path.of(System.getProperty("java.home"), "bin", "java").toString(), + "TLSWontNegotiateDisabledCipherAlgos", + "client", + Boolean.toString(!useDisabledAlgo), + Integer.toString(server.getListeningPort()) + ); + ProcessBuilder builder = new ProcessBuilder(command); + Process p = builder.inheritIO().start(); + server.run(); + p.destroy(); + } + } else if (args[0].equals("client")) { + try (TLSClient client = new TLSClient(Integer.parseInt(args[2]), useDisabledAlgo)) { + client.run(); + } + } + } + + private static class TLSClient extends SSLContextTemplate implements AutoCloseable { + private final SSLSocket socket; + + public TLSClient(int portNumber, boolean useDisableAlgo) throws Exception { + SSLContext context = createClientSSLContext(); + socket = (SSLSocket)context.getSocketFactory().createSocket("localhost", portNumber); + if (useDisableAlgo) { + socket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); + } + } + + public void run() throws IOException { + try { + socket.getOutputStream().write("SECRET MESSAGE".getBytes(StandardCharsets.UTF_8)); + throw new RuntimeException("SSL handshake completed successfully."); + } catch (SSLHandshakeException exc) { + if (!exc.getMessage().equals("Received fatal alert: handshake_failure")) { + throw new RuntimeException("Expected handshake_failure message. Got: " + + "\"" + exc.getMessage() + "\" message.", exc); + } + } + } + + @Override + public void close() throws Exception { + socket.close(); + } + } + + private static class TLSServer extends SSLContextTemplate implements AutoCloseable { + private SSLServerSocket serverSocket; + + public TLSServer(boolean useDisableAlgo) throws Exception { + SSLContext ctx = createServerSSLContext(); + serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0); + if (useDisableAlgo) { + serverSocket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); + } + } + + @Override + public void close() throws Exception { + serverSocket.close(); + } + + public int getListeningPort() { + return serverSocket.getLocalPort(); + } + + public void run() throws IOException { + try (Socket clientSocket = serverSocket.accept()) { + try { + byte[] bytes = clientSocket.getInputStream().readAllBytes(); + throw new RuntimeException("The expected SSLHandshakeException was not thrown."); + } catch (SSLHandshakeException exc) { + if (!exc.getMessage().contains("no cipher suites in common")) { + throw exc; + } else { + System.out.println("Success: The connection could not be negotiated (as expected.)"); + } + } + } + } + } +} From f24c5540ffd9ad6ef151338f64cd15f0a4df9ed1 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 6 Jul 2023 01:09:48 +0000 Subject: [PATCH 15/15] 8303086: SIGSEGV in JavaThread::is_interp_only_mode() Reviewed-by: pchilanomate Backport-of: 971c2efb698065c65dcf7373d8c3027f58d5f503 --- src/hotspot/share/prims/jvmtiEnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index cc9df0a3276..e82e4de0f66 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -575,7 +575,7 @@ JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, j if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { record_class_file_load_hook_enabled(); } - JvmtiVTMSTransitionDisabler disabler(event_thread); + JvmtiVTMSTransitionDisabler disabler; if (event_thread == nullptr) { // Can be called at Agent_OnLoad() time with event_thread == nullptr