+ * but more performant, and will not create or cache new nodes.
+ *
+ * @param moduleName The module name of the resource being tested for.
+ * @param resourcePath Trailing module-relative resource path, not starting
+ * with {@code '/'}.
+ */
+ public boolean containsResource(String moduleName, String resourcePath)
+ throws IOException {
+ ensureOpen();
+ return reader.containsResource(moduleName, resourcePath);
+ }
+
/**
* Returns a copy of the content of a resource node. The buffer returned by
* this method is not cached by the node, and each call returns a new array
@@ -276,10 +315,7 @@ public final class ImageReader implements AutoCloseable {
* Returns a node with the given name, or null if no resource or directory of
* that name exists.
*
- *
This is the only public API by which anything outside this class can access
- * {@code Node} instances either directly, or by resolving symbolic links.
- *
- *
Note also that there is no reentrant calling back to this method from within
+ *
Note that there is no reentrant calling back to this method from within
* the node handling code.
*
* @param name an absolute, {@code /}-separated path string, prefixed with either
@@ -291,6 +327,9 @@ public final class ImageReader implements AutoCloseable {
// We cannot get the root paths ("/modules" or "/packages") here
// because those nodes are already in the nodes cache.
if (name.startsWith(MODULES_ROOT + "/")) {
+ // This may perform two lookups, one for a directory (in
+ // "/modules/...") and one for a non-prefixed resource
+ // (with "/modules" removed).
node = buildModulesNode(name);
} else if (name.startsWith(PACKAGES_ROOT + "/")) {
node = buildPackagesNode(name);
@@ -307,6 +346,55 @@ public final class ImageReader implements AutoCloseable {
return node;
}
+ /**
+ * Returns a resource node in the given module, or null if no resource of
+ * that name exists.
+ *
+ *
Note that there is no reentrant calling back to this method from within
+ * the node handling code.
+ */
+ Node findResourceNode(String moduleName, String resourcePath) {
+ // Unlike findNode(), this method makes only one lookup in the
+ // underlying jimage, but can only reliably return resource nodes.
+ if (moduleName.indexOf('/') >= 0) {
+ throw new IllegalArgumentException("invalid module name: " + moduleName);
+ }
+ String nodeName = MODULES_ROOT + "/" + moduleName + "/" + resourcePath;
+ // Synchronize as tightly as possible to reduce locking contention.
+ synchronized (this) {
+ Node node = nodes.get(nodeName);
+ if (node == null) {
+ ImageLocation loc = findLocation(moduleName, resourcePath);
+ if (loc != null && isResource(loc)) {
+ node = newResource(nodeName, loc);
+ nodes.put(node.getName(), node);
+ }
+ return node;
+ } else {
+ return node.isResource() ? node : null;
+ }
+ }
+ }
+
+ /**
+ * Returns whether a resource exists in the given module.
+ *
+ *
This method is expected to be called frequently for resources
+ * which do not exist in the given module (e.g. as part of classpath
+ * search). As such, it skips checking the nodes cache and only checks
+ * for an entry in the jimage file, as this is faster if the resource
+ * is not present. This also means it doesn't need synchronization.
+ */
+ boolean containsResource(String moduleName, String resourcePath) {
+ if (moduleName.indexOf('/') >= 0) {
+ throw new IllegalArgumentException("invalid module name: " + moduleName);
+ }
+ // If the given module name is 'modules', then 'isResource()'
+ // returns false to prevent false positives.
+ ImageLocation loc = findLocation(moduleName, resourcePath);
+ return loc != null && isResource(loc);
+ }
+
/**
* Builds a node in the "/modules/..." namespace.
*
diff --git a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java
index 39f433d4041..370c151af84 100644
--- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java
+++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java
@@ -414,26 +414,18 @@ public final class SystemModuleFinders {
* Returns {@code true} if the given resource exists, {@code false}
* if not found.
*/
- private boolean containsResource(String resourcePath) throws IOException {
- Objects.requireNonNull(resourcePath);
+ private boolean containsResource(String module, String name) throws IOException {
+ Objects.requireNonNull(name);
if (closed)
throw new IOException("ModuleReader is closed");
ImageReader imageReader = SystemImage.reader();
- if (imageReader != null) {
- ImageReader.Node node = imageReader.findNode("/modules" + resourcePath);
- return node != null && node.isResource();
- } else {
- // not an images build
- return false;
- }
+ return imageReader != null && imageReader.containsResource(module, name);
}
@Override
public Optional find(String name) throws IOException {
- Objects.requireNonNull(name);
- String resourcePath = "/" + module + "/" + name;
- if (containsResource(resourcePath)) {
- URI u = JNUA.create("jrt", resourcePath);
+ if (containsResource(module, name)) {
+ URI u = JNUA.create("jrt", "/" + module + "/" + name);
return Optional.of(u);
} else {
return Optional.empty();
@@ -465,9 +457,7 @@ public final class SystemModuleFinders {
if (closed) {
throw new IOException("ModuleReader is closed");
}
- String nodeName = "/modules/" + module + "/" + name;
- ImageReader.Node node = reader.findNode(nodeName);
- return (node != null && node.isResource()) ? node : null;
+ return reader.findResourceNode(module, name);
}
@Override
diff --git a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
index 20b735fbdf3..71080950b80 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
@@ -87,8 +87,8 @@ public class JavaRuntimeURLConnection extends URLConnection {
if (module.isEmpty() || path == null) {
throw new IOException("cannot connect to jrt:/" + module);
}
- Node node = READER.findNode("/modules/" + module + "/" + path);
- if (node == null || !node.isResource()) {
+ Node node = READER.findResourceNode(module, path);
+ if (node == null) {
throw new IOException(module + "/" + path + " not found");
}
this.resourceNode = node;
diff --git a/test/jdk/jdk/internal/jimage/ImageReaderTest.java b/test/jdk/jdk/internal/jimage/ImageReaderTest.java
index 8db9a3768d4..de52ed1503d 100644
--- a/test/jdk/jdk/internal/jimage/ImageReaderTest.java
+++ b/test/jdk/jdk/internal/jimage/ImageReaderTest.java
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import tests.Helper;
import tests.JImageGenerator;
@@ -43,9 +44,11 @@ import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
@@ -122,6 +125,65 @@ public class ImageReaderTest {
}
}
+ @ParameterizedTest
+ @CsvSource(delimiter = ':', value = {
+ "modfoo:com/foo/Alpha.class",
+ "modbar:com/bar/One.class",
+ })
+ public void testResource_present(String modName, String resPath) throws IOException {
+ try (ImageReader reader = ImageReader.open(image)) {
+ assertNotNull(reader.findResourceNode(modName, resPath));
+ assertTrue(reader.containsResource(modName, resPath));
+
+ String canonicalNodeName = "/modules/" + modName + "/" + resPath;
+ Node node = reader.findNode(canonicalNodeName);
+ assertTrue(node != null && node.isResource());
+ }
+ }
+
+ @ParameterizedTest
+ @CsvSource(delimiter = ':', value = {
+ // Absolute resource names are not allowed.
+ "modfoo:/com/bar/One.class",
+ // Resource in wrong module.
+ "modfoo:com/bar/One.class",
+ "modbar:com/foo/Alpha.class",
+ // Directories are not returned.
+ "modfoo:com/foo",
+ "modbar:com/bar",
+ // JImage entries exist for these, but they are not resources.
+ "modules:modfoo/com/foo/Alpha.class",
+ "packages:com.foo/modfoo",
+ // Empty module names/paths do not find resources.
+ "'':modfoo/com/foo/Alpha.class",
+ "modfoo:''"})
+ public void testResource_absent(String modName, String resPath) throws IOException {
+ try (ImageReader reader = ImageReader.open(image)) {
+ assertNull(reader.findResourceNode(modName, resPath));
+ assertFalse(reader.containsResource(modName, resPath));
+
+ // Non-existent resources names should either not be found,
+ // or (in the case of directory nodes) not be resources.
+ String canonicalNodeName = "/modules/" + modName + "/" + resPath;
+ Node node = reader.findNode(canonicalNodeName);
+ assertTrue(node == null || !node.isResource());
+ }
+ }
+
+ @ParameterizedTest
+ @CsvSource(delimiter = ':', value = {
+ // Don't permit module names to contain paths.
+ "modfoo/com/bar:One.class",
+ "modfoo/com:bar/One.class",
+ "modules/modfoo/com:foo/Alpha.class",
+ })
+ public void testResource_invalid(String modName, String resPath) throws IOException {
+ try (ImageReader reader = ImageReader.open(image)) {
+ assertThrows(IllegalArgumentException.class, () -> reader.containsResource(modName, resPath));
+ assertThrows(IllegalArgumentException.class, () -> reader.findResourceNode(modName, resPath));
+ }
+ }
+
@Test
public void testPackageDirectories() throws IOException {
try (ImageReader reader = ImageReader.open(image)) {
From 01d7554b87fb7be8cab5dc12fd67eaba6585d2f3 Mon Sep 17 00:00:00 2001
From: Stefan Karlsson
Date: Wed, 17 Sep 2025 15:17:30 +0000
Subject: [PATCH 018/664] 8367486: Change prefix for platform-dependent
AtomicAccess files
Reviewed-by: kbarrett, ayang
---
.../{atomic_aix_ppc.hpp => atomicAccess_aix_ppc.hpp} | 8 ++++----
...omic_bsd_aarch64.hpp => atomicAccess_bsd_aarch64.hpp} | 9 ++++-----
.../{atomic_bsd_x86.hpp => atomicAccess_bsd_x86.hpp} | 8 ++++----
.../{atomic_bsd_zero.hpp => atomicAccess_bsd_zero.hpp} | 8 ++++----
src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp | 2 +-
..._linux_aarch64.hpp => atomicAccess_linux_aarch64.hpp} | 8 ++++----
.../{atomic_linux_arm.hpp => atomicAccess_linux_arm.hpp} | 8 ++++----
.../{atomic_linux_ppc.hpp => atomicAccess_linux_ppc.hpp} | 8 ++++----
...omic_linux_riscv.hpp => atomicAccess_linux_riscv.hpp} | 8 ++++----
...atomic_linux_s390.hpp => atomicAccess_linux_s390.hpp} | 6 +++---
.../{atomic_linux_x86.hpp => atomicAccess_linux_x86.hpp} | 8 ++++----
...atomic_linux_zero.hpp => atomicAccess_linux_zero.hpp} | 8 ++++----
src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp | 2 +-
...dows_aarch64.hpp => atomicAccess_windows_aarch64.hpp} | 6 +++---
...omic_windows_x86.hpp => atomicAccess_windows_x86.hpp} | 6 +++---
src/hotspot/share/runtime/atomicAccess.hpp | 2 +-
16 files changed, 52 insertions(+), 53 deletions(-)
rename src/hotspot/os_cpu/aix_ppc/{atomic_aix_ppc.hpp => atomicAccess_aix_ppc.hpp} (98%)
rename src/hotspot/os_cpu/bsd_aarch64/{atomic_bsd_aarch64.hpp => atomicAccess_bsd_aarch64.hpp} (95%)
rename src/hotspot/os_cpu/bsd_x86/{atomic_bsd_x86.hpp => atomicAccess_bsd_x86.hpp} (97%)
rename src/hotspot/os_cpu/bsd_zero/{atomic_bsd_zero.hpp => atomicAccess_bsd_zero.hpp} (96%)
rename src/hotspot/os_cpu/linux_aarch64/{atomic_linux_aarch64.hpp => atomicAccess_linux_aarch64.hpp} (97%)
rename src/hotspot/os_cpu/linux_arm/{atomic_linux_arm.hpp => atomicAccess_linux_arm.hpp} (97%)
rename src/hotspot/os_cpu/linux_ppc/{atomic_linux_ppc.hpp => atomicAccess_linux_ppc.hpp} (98%)
rename src/hotspot/os_cpu/linux_riscv/{atomic_linux_riscv.hpp => atomicAccess_linux_riscv.hpp} (97%)
rename src/hotspot/os_cpu/linux_s390/{atomic_linux_s390.hpp => atomicAccess_linux_s390.hpp} (98%)
rename src/hotspot/os_cpu/linux_x86/{atomic_linux_x86.hpp => atomicAccess_linux_x86.hpp} (97%)
rename src/hotspot/os_cpu/linux_zero/{atomic_linux_zero.hpp => atomicAccess_linux_zero.hpp} (96%)
rename src/hotspot/os_cpu/windows_aarch64/{atomic_windows_aarch64.hpp => atomicAccess_windows_aarch64.hpp} (96%)
rename src/hotspot/os_cpu/windows_x86/{atomic_windows_x86.hpp => atomicAccess_windows_x86.hpp} (97%)
diff --git a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/atomicAccess_aix_ppc.hpp
similarity index 98%
rename from src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp
rename to src/hotspot/os_cpu/aix_ppc/atomicAccess_aix_ppc.hpp
index d32f7c93ecf..3540e364bc6 100644
--- a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp
+++ b/src/hotspot/os_cpu/aix_ppc/atomicAccess_aix_ppc.hpp
@@ -23,8 +23,8 @@
*
*/
-#ifndef OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
-#define OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
+#ifndef OS_CPU_AIX_PPC_ATOMICACCESS_AIX_PPC_HPP
+#define OS_CPU_AIX_PPC_ATOMICACCESS_AIX_PPC_HPP
#ifndef PPC64
#error "Atomic currently only implemented for PPC64"
@@ -33,7 +33,7 @@
#include "orderAccess_aix_ppc.hpp"
#include "utilities/debug.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
//
// machine barrier instructions:
@@ -414,4 +414,4 @@ struct AtomicAccess::PlatformOrderedLoad {
}
};
-#endif // OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
+#endif // OS_CPU_AIX_PPC_ATOMICACCESS_AIX_PPC_HPP
diff --git a/src/hotspot/os_cpu/bsd_aarch64/atomic_bsd_aarch64.hpp b/src/hotspot/os_cpu/bsd_aarch64/atomicAccess_bsd_aarch64.hpp
similarity index 95%
rename from src/hotspot/os_cpu/bsd_aarch64/atomic_bsd_aarch64.hpp
rename to src/hotspot/os_cpu/bsd_aarch64/atomicAccess_bsd_aarch64.hpp
index 1ecdd59f59e..3d2c632ace8 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/atomic_bsd_aarch64.hpp
+++ b/src/hotspot/os_cpu/bsd_aarch64/atomicAccess_bsd_aarch64.hpp
@@ -24,12 +24,12 @@
*
*/
-#ifndef OS_CPU_BSD_AARCH64_ATOMIC_BSD_AARCH64_HPP
-#define OS_CPU_BSD_AARCH64_ATOMIC_BSD_AARCH64_HPP
+#ifndef OS_CPU_BSD_AARCH64_ATOMICACCESS_BSD_AARCH64_HPP
+#define OS_CPU_BSD_AARCH64_ATOMICACCESS_BSD_AARCH64_HPP
#include "utilities/debug.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
// Note that memory_order_conservative requires a full barrier after atomic stores.
// See https://patchwork.kernel.org/patch/3575821/
@@ -129,5 +129,4 @@ struct AtomicAccess::PlatformOrderedStore
void operator()(volatile T* p, T v) const { release_store(p, v); OrderAccess::fence(); }
};
-
-#endif // OS_CPU_BSD_AARCH64_ATOMIC_BSD_AARCH64_HPP
+#endif // OS_CPU_BSD_AARCH64_ATOMICACCESS_BSD_AARCH64_HPP
diff --git a/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp b/src/hotspot/os_cpu/bsd_x86/atomicAccess_bsd_x86.hpp
similarity index 97%
rename from src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp
rename to src/hotspot/os_cpu/bsd_x86/atomicAccess_bsd_x86.hpp
index 8fbc319e766..975580fbd71 100644
--- a/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp
+++ b/src/hotspot/os_cpu/bsd_x86/atomicAccess_bsd_x86.hpp
@@ -22,10 +22,10 @@
*
*/
-#ifndef OS_CPU_BSD_X86_ATOMIC_BSD_X86_HPP
-#define OS_CPU_BSD_X86_ATOMIC_BSD_X86_HPP
+#ifndef OS_CPU_BSD_X86_ATOMICACCESS_BSD_X86_HPP
+#define OS_CPU_BSD_X86_ATOMICACCESS_BSD_X86_HPP
-// Implementation of class atomic
+// Implementation of class AtomicAccess
template
struct AtomicAccess::PlatformAdd {
@@ -230,4 +230,4 @@ struct AtomicAccess::PlatformOrderedStore<8, RELEASE_X_FENCE>
};
#endif // AMD64
-#endif // OS_CPU_BSD_X86_ATOMIC_BSD_X86_HPP
+#endif // OS_CPU_BSD_X86_ATOMICACCESS_BSD_X86_HPP
diff --git a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp b/src/hotspot/os_cpu/bsd_zero/atomicAccess_bsd_zero.hpp
similarity index 96%
rename from src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp
rename to src/hotspot/os_cpu/bsd_zero/atomicAccess_bsd_zero.hpp
index b5cedac867b..6a720dac54e 100644
--- a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp
+++ b/src/hotspot/os_cpu/bsd_zero/atomicAccess_bsd_zero.hpp
@@ -23,13 +23,13 @@
*
*/
-#ifndef OS_CPU_BSD_ZERO_ATOMIC_BSD_ZERO_HPP
-#define OS_CPU_BSD_ZERO_ATOMIC_BSD_ZERO_HPP
+#ifndef OS_CPU_BSD_ZERO_ATOMICACCESS_BSD_ZERO_HPP
+#define OS_CPU_BSD_ZERO_ATOMICACCESS_BSD_ZERO_HPP
#include "orderAccess_bsd_zero.hpp"
#include "runtime/os.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
template
struct AtomicAccess::PlatformAdd {
@@ -149,4 +149,4 @@ inline void AtomicAccess::PlatformStore<8>::operator()(T volatile* dest,
__atomic_store(dest, &store_value, __ATOMIC_RELAXED);
}
-#endif // OS_CPU_BSD_ZERO_ATOMIC_BSD_ZERO_HPP
+#endif // OS_CPU_BSD_ZERO_ATOMICACCESS_BSD_ZERO_HPP
diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
index 3fefbdbe56c..facad184426 100644
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
@@ -24,7 +24,6 @@
*/
#include "asm/assembler.inline.hpp"
-#include "atomic_bsd_zero.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
@@ -36,6 +35,7 @@
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
+#include "runtime/atomicAccess.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/atomicAccess_linux_aarch64.hpp
similarity index 97%
rename from src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp
rename to src/hotspot/os_cpu/linux_aarch64/atomicAccess_linux_aarch64.hpp
index 4940cbdc246..6e5f53edfa3 100644
--- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp
+++ b/src/hotspot/os_cpu/linux_aarch64/atomicAccess_linux_aarch64.hpp
@@ -23,13 +23,13 @@
*
*/
-#ifndef OS_CPU_LINUX_AARCH64_ATOMIC_LINUX_AARCH64_HPP
-#define OS_CPU_LINUX_AARCH64_ATOMIC_LINUX_AARCH64_HPP
+#ifndef OS_CPU_LINUX_AARCH64_ATOMICACCESS_LINUX_AARCH64_HPP
+#define OS_CPU_LINUX_AARCH64_ATOMICACCESS_LINUX_AARCH64_HPP
#include "atomic_aarch64.hpp"
#include "runtime/vm_version.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
// Note that memory_order_conservative requires a full barrier after atomic stores.
// See https://patchwork.kernel.org/patch/3575821/
@@ -217,4 +217,4 @@ struct AtomicAccess::PlatformOrderedStore
void operator()(volatile T* p, T v) const { release_store(p, v); OrderAccess::fence(); }
};
-#endif // OS_CPU_LINUX_AARCH64_ATOMIC_LINUX_AARCH64_HPP
+#endif // OS_CPU_LINUX_AARCH64_ATOMICACCESS_LINUX_AARCH64_HPP
diff --git a/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp b/src/hotspot/os_cpu/linux_arm/atomicAccess_linux_arm.hpp
similarity index 97%
rename from src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp
rename to src/hotspot/os_cpu/linux_arm/atomicAccess_linux_arm.hpp
index db00c347dea..5b5f9da51a6 100644
--- a/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp
+++ b/src/hotspot/os_cpu/linux_arm/atomicAccess_linux_arm.hpp
@@ -22,14 +22,14 @@
*
*/
-#ifndef OS_CPU_LINUX_ARM_ATOMIC_LINUX_ARM_HPP
-#define OS_CPU_LINUX_ARM_ATOMIC_LINUX_ARM_HPP
+#ifndef OS_CPU_LINUX_ARM_ATOMICACCESS_LINUX_ARM_HPP
+#define OS_CPU_LINUX_ARM_ATOMICACCESS_LINUX_ARM_HPP
#include "memory/allStatic.hpp"
#include "runtime/os.hpp"
#include "runtime/vm_version.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
class ARMAtomicFuncs : AllStatic {
public:
@@ -178,4 +178,4 @@ inline T AtomicAccess::PlatformCmpxchg<8>::operator()(T volatile* dest,
return cmpxchg_using_helper(reorder_cmpxchg_long_func, dest, compare_value, exchange_value);
}
-#endif // OS_CPU_LINUX_ARM_ATOMIC_LINUX_ARM_HPP
+#endif // OS_CPU_LINUX_ARM_ATOMICACCESS_LINUX_ARM_HPP
diff --git a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/atomicAccess_linux_ppc.hpp
similarity index 98%
rename from src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp
rename to src/hotspot/os_cpu/linux_ppc/atomicAccess_linux_ppc.hpp
index 9f1d90c26bd..f4eac1207bf 100644
--- a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp
+++ b/src/hotspot/os_cpu/linux_ppc/atomicAccess_linux_ppc.hpp
@@ -23,8 +23,8 @@
*
*/
-#ifndef OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
-#define OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
+#ifndef OS_CPU_LINUX_PPC_ATOMICACCESS_LINUX_PPC_HPP
+#define OS_CPU_LINUX_PPC_ATOMICACCESS_LINUX_PPC_HPP
#ifndef PPC64
#error "Atomic currently only implemented for PPC64"
@@ -33,7 +33,7 @@
#include "orderAccess_linux_ppc.hpp"
#include "utilities/debug.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
//
// machine barrier instructions:
@@ -392,4 +392,4 @@ struct AtomicAccess::PlatformOrderedLoad
}
};
-#endif // OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
+#endif // OS_CPU_LINUX_PPC_ATOMICACCESS_LINUX_PPC_HPP
diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomicAccess_linux_riscv.hpp
similarity index 97%
rename from src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp
rename to src/hotspot/os_cpu/linux_riscv/atomicAccess_linux_riscv.hpp
index f713465edeb..6d57ea55a83 100644
--- a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp
+++ b/src/hotspot/os_cpu/linux_riscv/atomicAccess_linux_riscv.hpp
@@ -23,12 +23,12 @@
*
*/
-#ifndef OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP
-#define OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP
+#ifndef OS_CPU_LINUX_RISCV_ATOMICACCESS_LINUX_RISCV_HPP
+#define OS_CPU_LINUX_RISCV_ATOMICACCESS_LINUX_RISCV_HPP
#include "runtime/vm_version.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
// Note that memory_order_conservative requires a full barrier after atomic stores.
// See https://patchwork.kernel.org/patch/3575821/
@@ -226,4 +226,4 @@ struct AtomicAccess::PlatformOrderedStore
#undef FULL_COMPILER_ATOMIC_SUPPORT
-#endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP
+#endif // OS_CPU_LINUX_RISCV_ATOMICACCESS_LINUX_RISCV_HPP
diff --git a/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp b/src/hotspot/os_cpu/linux_s390/atomicAccess_linux_s390.hpp
similarity index 98%
rename from src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp
rename to src/hotspot/os_cpu/linux_s390/atomicAccess_linux_s390.hpp
index ec620e3907a..5849d69ae2f 100644
--- a/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp
+++ b/src/hotspot/os_cpu/linux_s390/atomicAccess_linux_s390.hpp
@@ -23,8 +23,8 @@
*
*/
-#ifndef OS_CPU_LINUX_S390_ATOMIC_LINUX_S390_HPP
-#define OS_CPU_LINUX_S390_ATOMIC_LINUX_S390_HPP
+#ifndef OS_CPU_LINUX_S390_ATOMICACCESS_LINUX_S390_HPP
+#define OS_CPU_LINUX_S390_ATOMICACCESS_LINUX_S390_HPP
#include "runtime/atomicAccess.hpp"
#include "runtime/os.hpp"
@@ -345,4 +345,4 @@ struct AtomicAccess::PlatformOrderedLoad
T operator()(const volatile T* p) const { T t = *p; OrderAccess::acquire(); return t; }
};
-#endif // OS_CPU_LINUX_S390_ATOMIC_LINUX_S390_HPP
+#endif // OS_CPU_LINUX_S390_ATOMICACCESS_LINUX_S390_HPP
diff --git a/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/atomicAccess_linux_x86.hpp
similarity index 97%
rename from src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp
rename to src/hotspot/os_cpu/linux_x86/atomicAccess_linux_x86.hpp
index 561224f56be..c9af982525d 100644
--- a/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp
+++ b/src/hotspot/os_cpu/linux_x86/atomicAccess_linux_x86.hpp
@@ -22,10 +22,10 @@
*
*/
-#ifndef OS_CPU_LINUX_X86_ATOMIC_LINUX_X86_HPP
-#define OS_CPU_LINUX_X86_ATOMIC_LINUX_X86_HPP
+#ifndef OS_CPU_LINUX_X86_ATOMICACCESS_LINUX_X86_HPP
+#define OS_CPU_LINUX_X86_ATOMICACCESS_LINUX_X86_HPP
-// Implementation of class atomic
+// Implementation of class AtomicAccess
template
struct AtomicAccess::PlatformAdd {
@@ -230,4 +230,4 @@ struct AtomicAccess::PlatformOrderedStore<8, RELEASE_X_FENCE>
};
#endif // AMD64
-#endif // OS_CPU_LINUX_X86_ATOMIC_LINUX_X86_HPP
+#endif // OS_CPU_LINUX_X86_ATOMICACCESS_LINUX_X86_HPP
diff --git a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/atomicAccess_linux_zero.hpp
similarity index 96%
rename from src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp
rename to src/hotspot/os_cpu/linux_zero/atomicAccess_linux_zero.hpp
index 05d567d3e28..376ef7a9dc9 100644
--- a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp
+++ b/src/hotspot/os_cpu/linux_zero/atomicAccess_linux_zero.hpp
@@ -23,12 +23,12 @@
*
*/
-#ifndef OS_CPU_LINUX_ZERO_ATOMIC_LINUX_ZERO_HPP
-#define OS_CPU_LINUX_ZERO_ATOMIC_LINUX_ZERO_HPP
+#ifndef OS_CPU_LINUX_ZERO_ATOMICACCESS_LINUX_ZERO_HPP
+#define OS_CPU_LINUX_ZERO_ATOMICACCESS_LINUX_ZERO_HPP
#include "orderAccess_linux_zero.hpp"
-// Implementation of class atomic
+// Implementation of class AtomicAccess
template
struct AtomicAccess::PlatformAdd {
@@ -149,4 +149,4 @@ inline void AtomicAccess::PlatformStore<8>::operator()(T volatile* dest,
__atomic_store(dest, &store_value, __ATOMIC_RELAXED);
}
-#endif // OS_CPU_LINUX_ZERO_ATOMIC_LINUX_ZERO_HPP
+#endif // OS_CPU_LINUX_ZERO_ATOMICACCESS_LINUX_ZERO_HPP
diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
index c9ac461851a..0ea379fec50 100644
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
@@ -24,7 +24,6 @@
*/
#include "asm/assembler.inline.hpp"
-#include "atomic_linux_zero.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
@@ -36,6 +35,7 @@
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
+#include "runtime/atomicAccess.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
diff --git a/src/hotspot/os_cpu/windows_aarch64/atomic_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp
similarity index 96%
rename from src/hotspot/os_cpu/windows_aarch64/atomic_windows_aarch64.hpp
rename to src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp
index 42c5b0e4a6c..62b6e3f87ec 100644
--- a/src/hotspot/os_cpu/windows_aarch64/atomic_windows_aarch64.hpp
+++ b/src/hotspot/os_cpu/windows_aarch64/atomicAccess_windows_aarch64.hpp
@@ -23,8 +23,8 @@
*
*/
-#ifndef OS_CPU_WINDOWS_AARCH64_ATOMIC_WINDOWS_AARCH64_HPP
-#define OS_CPU_WINDOWS_AARCH64_ATOMIC_WINDOWS_AARCH64_HPP
+#ifndef OS_CPU_WINDOWS_AARCH64_ATOMICACCESS_WINDOWS_AARCH64_HPP
+#define OS_CPU_WINDOWS_AARCH64_ATOMICACCESS_WINDOWS_AARCH64_HPP
#include
#include "runtime/os.hpp"
@@ -109,4 +109,4 @@ DEFINE_INTRINSIC_CMPXCHG(InterlockedCompareExchange64, __int64)
#undef DEFINE_INTRINSIC_CMPXCHG
-#endif // OS_CPU_WINDOWS_AARCH64_ATOMIC_WINDOWS_AARCH64_HPP
+#endif // OS_CPU_WINDOWS_AARCH64_ATOMICACCESS_WINDOWS_AARCH64_HPP
diff --git a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/atomicAccess_windows_x86.hpp
similarity index 97%
rename from src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp
rename to src/hotspot/os_cpu/windows_x86/atomicAccess_windows_x86.hpp
index 4529da29092..a95da151688 100644
--- a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp
+++ b/src/hotspot/os_cpu/windows_x86/atomicAccess_windows_x86.hpp
@@ -22,8 +22,8 @@
*
*/
-#ifndef OS_CPU_WINDOWS_X86_ATOMIC_WINDOWS_X86_HPP
-#define OS_CPU_WINDOWS_X86_ATOMIC_WINDOWS_X86_HPP
+#ifndef OS_CPU_WINDOWS_X86_ATOMICACCESS_WINDOWS_X86_HPP
+#define OS_CPU_WINDOWS_X86_ATOMICACCESS_WINDOWS_X86_HPP
#include
#include "runtime/os.hpp"
@@ -111,4 +111,4 @@ DEFINE_INTRINSIC_CMPXCHG(InterlockedCompareExchange64, __int64)
#undef DEFINE_INTRINSIC_CMPXCHG
-#endif // OS_CPU_WINDOWS_X86_ATOMIC_WINDOWS_X86_HPP
+#endif // OS_CPU_WINDOWS_X86_ATOMICACCESS_WINDOWS_X86_HPP
diff --git a/src/hotspot/share/runtime/atomicAccess.hpp b/src/hotspot/share/runtime/atomicAccess.hpp
index 0ee60d2b7b7..ff972b31a26 100644
--- a/src/hotspot/share/runtime/atomicAccess.hpp
+++ b/src/hotspot/share/runtime/atomicAccess.hpp
@@ -859,7 +859,7 @@ class ScopedFence : public ScopedFenceGeneral {
// platform specific in-line definitions - must come before shared definitions
-#include OS_CPU_HEADER(atomic)
+#include OS_CPU_HEADER(atomicAccess)
// shared in-line definitions
From 6f493b4d2e7120cbe34fb70d595f7626655b47a9 Mon Sep 17 00:00:00 2001
From: Cesar Soares Lucas
Date: Wed, 17 Sep 2025 16:52:13 +0000
Subject: [PATCH 019/664] 8361699: C2: assert(can_reduce_phi(n->as_Phi()))
failed: Sanity: previous reducible Phi is no longer reducible before SUT
Reviewed-by: rcastanedalo
---
src/hotspot/share/opto/escape.cpp | 8 +++
...stReduceAllocationNotReducibleAnymore.java | 63 +++++++++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationNotReducibleAnymore.java
diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp
index eff482350b6..e6a593770b4 100644
--- a/src/hotspot/share/opto/escape.cpp
+++ b/src/hotspot/share/opto/escape.cpp
@@ -3129,6 +3129,14 @@ void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArrayis_LocalVar()) {
+ Node* phi = use->ideal_node();
+ if (phi->Opcode() == Op_Phi && reducible_merges.member(phi) && !can_reduce_phi(phi->as_Phi())) {
+ set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is merged in a non-reducible phi"));
+ reducible_merges.yank(phi);
+ found_nsr_alloc = true;
+ break;
+ }
}
}
}
diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationNotReducibleAnymore.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationNotReducibleAnymore.java
new file mode 100644
index 00000000000..16bdd68c93c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationNotReducibleAnymore.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8361699
+ * @summary Check that NSR state propagate correctly to initially reducible Phis
+ * and turns them into non-reducible Phis.
+ * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationNotReducibleAnymore*::*
+ * -XX:CompileCommand=dontinline,*TestReduceAllocationNotReducibleAnymore*::*
+ * -Xcomp compiler.escapeAnalysis.TestReduceAllocationNotReducibleAnymore
+ * @run main compiler.escapeAnalysis.TestReduceAllocationNotReducibleAnymore
+ */
+
+package compiler.escapeAnalysis;
+
+public class TestReduceAllocationNotReducibleAnymore {
+ public static void main(String[] args) {
+ for (int i = 0; i < 100; i++) {
+ test(4, null);
+ }
+ }
+
+ static void test(int x, A a) {
+ Object[] objects = { new Object() };
+ Object object = new Object();
+ for (int i = 0; i < 150; i++) {
+ try {
+ objects[x] = object;
+ object = new byte[10];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ }
+ try {
+ a.foo();
+ } catch (NullPointerException e) {
+ }
+ }
+ }
+
+ class A {
+ void foo() {}
+ }
+}
From 18dc186a8f4820ed78c21173713dd127ef512e1f Mon Sep 17 00:00:00 2001
From: Damon Nguyen
Date: Wed, 17 Sep 2025 18:07:29 +0000
Subject: [PATCH 020/664] 8367790: Remove
java/awt/PopupMenu/PopupMenuLocation.java from ProblemList
Reviewed-by: aivanov, azvegint
---
test/jdk/ProblemList.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 528a33c1bd5..d1987c873a6 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -471,7 +471,7 @@ java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java 8233568 m
java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java 8233568 macosx-all
java/awt/event/KeyEvent/DeadKey/deadKeyMacOSX.java 8233568 macosx-all
java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed.java 8238720 windows-all
-java/awt/PopupMenu/PopupMenuLocation.java 8259913,8315878 windows-all,macosx-aarch64
+java/awt/PopupMenu/PopupMenuLocation.java 8259913 windows-all
java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720,8324782 windows-all,macosx-all
java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8324782 windows-all,macosx-all
java/awt/GridBagLayout/ComponentShortage.java 8355280 windows-all,linux-all
From f7ce3a1b5f38143f17b5015ca5b714ec0e708f54 Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk
Date: Wed, 17 Sep 2025 19:22:30 +0000
Subject: [PATCH 021/664] 8365790: Shutdown hook for application image does not
work on Windows
Reviewed-by: almatvee
---
.../native/applauncher/WinLauncher.cpp | 25 +++-
.../windows/native/common/Executor.cpp | 6 +-
.../windows/native/common/Executor.h | 13 +-
.../tools/jpackage/apps/UseShutdownHook.java | 88 ++++++++++++
.../helpers/jdk/jpackage/test/CfgFile.java | 12 +-
.../helpers/jdk/jpackage/test/TKit.java | 63 +++++----
.../jpackage/resources/Win8365790Test.ps1 | 83 ++++++++++++
.../jpackage/windows/Win8365790Test.java | 128 ++++++++++++++++++
8 files changed, 380 insertions(+), 38 deletions(-)
create mode 100644 test/jdk/tools/jpackage/apps/UseShutdownHook.java
create mode 100644 test/jdk/tools/jpackage/resources/Win8365790Test.ps1
create mode 100644 test/jdk/tools/jpackage/windows/Win8365790Test.java
diff --git a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp
index fe59cd94b84..8b3c3bb6aef 100644
--- a/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp
+++ b/src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025, 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
@@ -256,6 +256,16 @@ bool needRestartLauncher(AppLauncher& appLauncher, CfgFile& cfgFile) {
}
+void enableConsoleCtrlHandler(bool enable) {
+ if (!SetConsoleCtrlHandler(NULL, enable ? FALSE : TRUE)) {
+ JP_THROW(SysError(tstrings::any() << "SetConsoleCtrlHandler(NULL, "
+ << (enable ? "FALSE" : "TRUE")
+ << ") failed",
+ SetConsoleCtrlHandler));
+ }
+}
+
+
void launchApp() {
// [RT-31061] otherwise UI can be left in back of other windows.
::AllowSetForegroundWindow(ASFW_ANY);
@@ -310,6 +320,19 @@ void launchApp() {
exec.arg(arg);
});
+ exec.afterProcessCreated([&](HANDLE pid) {
+ //
+ // Ignore Ctrl+C in the current process.
+ // This will prevent child process termination without allowing
+ // it to handle Ctrl+C events.
+ //
+ // Disable the default Ctrl+C handler *after* the child process
+ // has been created as it is inheritable and we want the child
+ // process to have the default handler.
+ //
+ enableConsoleCtrlHandler(false);
+ });
+
DWORD exitCode = RunExecutorWithMsgLoop::apply(exec);
exit(exitCode);
diff --git a/src/jdk.jpackage/windows/native/common/Executor.cpp b/src/jdk.jpackage/windows/native/common/Executor.cpp
index edb850afdbb..dfb6b299e5d 100644
--- a/src/jdk.jpackage/windows/native/common/Executor.cpp
+++ b/src/jdk.jpackage/windows/native/common/Executor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025, 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
@@ -161,6 +161,10 @@ UniqueHandle Executor::startProcess(UniqueHandle* threadHandle) const {
}
}
+ if (afterProcessCreatedCallback) {
+ afterProcessCreatedCallback(processInfo.hProcess);
+ }
+
// Return process handle.
return UniqueHandle(processInfo.hProcess);
}
diff --git a/src/jdk.jpackage/windows/native/common/Executor.h b/src/jdk.jpackage/windows/native/common/Executor.h
index a6edcbd4f76..09c9f85bac6 100644
--- a/src/jdk.jpackage/windows/native/common/Executor.h
+++ b/src/jdk.jpackage/windows/native/common/Executor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
#ifndef EXECUTOR_H
#define EXECUTOR_H
+#include
+
#include "tstrings.h"
#include "UniqueHandle.h"
@@ -97,6 +99,14 @@ public:
*/
int execAndWaitForExit() const;
+ /**
+ * Call provided function after the process hass been created.
+ */
+ Executor& afterProcessCreated(const std::function& v) {
+ afterProcessCreatedCallback = v;
+ return *this;
+ }
+
private:
UniqueHandle startProcess(UniqueHandle* threadHandle=0) const;
@@ -106,6 +116,7 @@ private:
HANDLE jobHandle;
tstring_array argsArray;
std::wstring appPath;
+ std::function afterProcessCreatedCallback;
};
#endif // #ifndef EXECUTOR_H
diff --git a/test/jdk/tools/jpackage/apps/UseShutdownHook.java b/test/jdk/tools/jpackage/apps/UseShutdownHook.java
new file mode 100644
index 00000000000..c558ee85701
--- /dev/null
+++ b/test/jdk/tools/jpackage/apps/UseShutdownHook.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+public class UseShutdownHook {
+
+ public static void main(String[] args) throws InterruptedException {
+ trace("Started");
+
+ var outputFile = Path.of(args[0]);
+ trace(String.format("Write output in [%s] file", outputFile));
+
+ var shutdownTimeoutSeconds = Integer.parseInt(args[1]);
+ trace(String.format("Automatically shutdown the app in %ss", shutdownTimeoutSeconds));
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ output(outputFile, "shutdown hook executed");
+ }
+ });
+
+ var startTime = System.currentTimeMillis();
+ var lock = new Object();
+ do {
+ synchronized (lock) {
+ lock.wait(shutdownTimeoutSeconds * 1000);
+ }
+ } while ((System.currentTimeMillis() - startTime) < (shutdownTimeoutSeconds * 1000));
+
+ output(outputFile, "exit");
+ }
+
+ private static void output(Path outputFilePath, String msg) {
+
+ trace(String.format("Writing [%s] into [%s]", msg, outputFilePath));
+
+ try {
+ Files.createDirectories(outputFilePath.getParent());
+ Files.writeString(outputFilePath, msg, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static void trace(String msg) {
+ Date time = new Date(System.currentTimeMillis());
+ msg = String.format("UseShutdownHook [%s]: %s", SDF.format(time), msg);
+ System.out.println(msg);
+ try {
+ Files.write(traceFile, List.of(msg), StandardOpenOption.APPEND, StandardOpenOption.CREATE);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss.SSS");
+
+ private static final Path traceFile = Path.of(System.getProperty("jpackage.test.trace-file"));
+}
diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java
index 9df28b3915e..52e8ecf819b 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025, 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
@@ -59,13 +59,18 @@ public final class CfgFile {
}
}
- public void addValue(String sectionName, String key, String value) {
+ public CfgFile addValue(String sectionName, String key, String value) {
var section = getSection(sectionName);
if (section == null) {
section = new Section(sectionName, new ArrayList<>());
data.add(section);
}
section.data.add(Map.entry(key, value));
+ return this;
+ }
+
+ public CfgFile add(CfgFile other) {
+ return combine(this, other);
}
public CfgFile() {
@@ -89,7 +94,7 @@ public final class CfgFile {
this.id = id;
}
- public void save(Path path) {
+ public CfgFile save(Path path) {
var lines = data.stream().flatMap(section -> {
return Stream.concat(
Stream.of(String.format("[%s]", section.name)),
@@ -98,6 +103,7 @@ public final class CfgFile {
}));
});
TKit.createTextFile(path, lines);
+ return this;
}
private Section getSection(String name) {
diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
index a94dfa135c1..b3f188bb371 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
@@ -41,7 +41,6 @@ import java.nio.file.StandardCopyOption;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
-import java.nio.file.WatchService;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
@@ -611,44 +610,44 @@ public final class TKit {
trace(String.format("Wait for file [%s] to be available",
fileToWaitFor.toAbsolutePath()));
- WatchService ws = FileSystems.getDefault().newWatchService();
+ try (var ws = FileSystems.getDefault().newWatchService()) {
- Path watchDirectory = fileToWaitFor.toAbsolutePath().getParent();
- watchDirectory.register(ws, ENTRY_CREATE, ENTRY_MODIFY);
+ Path watchDirectory = fileToWaitFor.toAbsolutePath().getParent();
+ watchDirectory.register(ws, ENTRY_CREATE, ENTRY_MODIFY);
- var waitUntil = Instant.now().plus(timeout);
- for (;;) {
- var remainderTimeout = Instant.now().until(waitUntil);
- assertTrue(remainderTimeout.isPositive(), String.format(
- "Check timeout value %dms is positive", remainderTimeout.toMillis()));
+ var waitUntil = Instant.now().plus(timeout);
+ for (;;) {
+ var remainderTimeout = Instant.now().until(waitUntil);
+ assertTrue(remainderTimeout.isPositive(), String.format(
+ "Check timeout value %dms is positive", remainderTimeout.toMillis()));
- WatchKey key = ThrowingSupplier.toSupplier(() -> {
- return ws.poll(remainderTimeout.toMillis(), TimeUnit.MILLISECONDS);
- }).get();
- if (key == null) {
- if (Files.exists(fileToWaitFor)) {
- trace(String.format(
- "File [%s] is available after poll timeout expired",
- fileToWaitFor));
- return;
+ WatchKey key = ThrowingSupplier.toSupplier(() -> {
+ return ws.poll(remainderTimeout.toMillis(), TimeUnit.MILLISECONDS);
+ }).get();
+ if (key == null) {
+ if (Files.exists(fileToWaitFor)) {
+ trace(String.format(
+ "File [%s] is available after poll timeout expired",
+ fileToWaitFor));
+ return;
+ }
+ assertUnexpected(String.format("Timeout %dms expired", remainderTimeout.toMillis()));
}
- assertUnexpected(String.format("Timeout %dms expired", remainderTimeout.toMillis()));
- }
- for (WatchEvent> event : key.pollEvents()) {
- if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
- continue;
+ for (WatchEvent> event : key.pollEvents()) {
+ if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
+ continue;
+ }
+ Path contextPath = (Path) event.context();
+ if (Files.exists(fileToWaitFor) && Files.isSameFile(watchDirectory.resolve(contextPath), fileToWaitFor)) {
+ trace(String.format("File [%s] is available", fileToWaitFor));
+ return;
+ }
}
- Path contextPath = (Path) event.context();
- if (Files.isSameFile(watchDirectory.resolve(contextPath),
- fileToWaitFor)) {
- trace(String.format("File [%s] is available", fileToWaitFor));
- return;
- }
- }
- if (!key.reset()) {
- assertUnexpected("Watch key invalidated");
+ if (!key.reset()) {
+ assertUnexpected("Watch key invalidated");
+ }
}
}
}
diff --git a/test/jdk/tools/jpackage/resources/Win8365790Test.ps1 b/test/jdk/tools/jpackage/resources/Win8365790Test.ps1
new file mode 100644
index 00000000000..3a7d8c9a90b
--- /dev/null
+++ b/test/jdk/tools/jpackage/resources/Win8365790Test.ps1
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2025, 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.
+#
+
+param (
+ # Path to executable to start.
+ [Parameter(Mandatory=$true)]
+ [string]$Executable,
+
+ # Timeout to wait after the executable has been started.
+ [Parameter(Mandatory=$true)]
+ [double]$TimeoutSeconds
+)
+
+$type = @{
+ TypeDefinition = @'
+using System;
+using System.Runtime.InteropServices;
+
+namespace Stuff {
+
+ internal struct Details {
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);
+ }
+
+ public struct Facade {
+ public static void GenerateConsoleCtrlEvent() {
+ if (!Details.GenerateConsoleCtrlEvent(0, 0)) {
+ reportLastErrorAndExit("GenerateConsoleCtrlEvent");
+ }
+ }
+
+ internal static void reportLastErrorAndExit(String func) {
+ int errorCode = Marshal.GetLastWin32Error();
+ Console.Error.WriteLine(func + " function failed with error code: " + errorCode);
+ Environment.Exit(100);
+ }
+ }
+}
+'@
+}
+Add-Type @type
+
+Set-PSDebug -Trace 2
+
+# Launch the target executable.
+# `-NoNewWindow` parameter will attach the started process to the existing console.
+$childProc = Start-Process -PassThru -NoNewWindow $Executable
+
+# Wait a bit to let the started process complete initialization.
+Start-Sleep -Seconds $TimeoutSeconds
+
+# Call GenerateConsoleCtrlEvent to send a CTRL+C event to the launched executable.
+# CTRL+C event will be sent to all processes attached to the console of the current process,
+# i.e., it will be sent to this PowerShell process and to the started $Executable process because
+# it was configured to attach to the existing console (the console of this PowerShell process).
+[Stuff.Facade]::GenerateConsoleCtrlEvent()
+
+# Wait for child process termination
+Wait-Process -InputObject $childProc
+
+Exit 0
diff --git a/test/jdk/tools/jpackage/windows/Win8365790Test.java b/test/jdk/tools/jpackage/windows/Win8365790Test.java
new file mode 100644
index 00000000000..6376a16cecc
--- /dev/null
+++ b/test/jdk/tools/jpackage/windows/Win8365790Test.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2025, 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 static jdk.jpackage.test.HelloApp.configureAndExecute;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import jdk.jpackage.test.AdditionalLauncher;
+import jdk.jpackage.test.Annotations.Test;
+import jdk.jpackage.test.CfgFile;
+import jdk.jpackage.test.Executor;
+import jdk.jpackage.test.JPackageCommand;
+import jdk.jpackage.test.LauncherVerifier;
+import jdk.jpackage.test.TKit;
+
+/**
+ * Test the child process has a chance to handle Ctrl+C signal.
+ */
+
+/*
+ * @test
+ * @summary Test case for JDK-8365790
+ * @library /test/jdk/tools/jpackage/helpers
+ * @build jdk.jpackage.test.*
+ * @build Win8365790Test
+ * @requires (os.family == "windows")
+ * @run main/othervm/timeout=100 -Xmx512m jdk.jpackage.test.Main
+ * --jpt-run=Win8365790Test
+ */
+public class Win8365790Test {
+
+ @Test
+ public void test() throws InterruptedException, IOException {
+
+ var outputDir = TKit.createTempDirectory("response-dir");
+
+ var mainOutputFile = outputDir.resolve("output.txt");
+ var mainTraceFile = outputDir.resolve("trace.txt");
+
+ var probeOutputFile = outputDir.resolve("probe-output.txt");
+ var probeTraceFile = outputDir.resolve("probe-trace.txt");
+
+ var cmd = JPackageCommand
+ .helloAppImage(TEST_APP_JAVA + "*UseShutdownHook")
+ .ignoreFakeRuntime()
+ .addArguments("--java-options", "-Djpackage.test.trace-file=" + mainTraceFile.toString())
+ .addArguments("--arguments", mainOutputFile.toString())
+ .addArguments("--arguments", Long.toString(Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS).getSeconds()));
+
+ new AdditionalLauncher("probe")
+ .withoutVerifyActions(LauncherVerifier.Action.values())
+ .addJavaOptions("-Djpackage.test.trace-file=" + probeTraceFile.toString())
+ .addDefaultArguments(probeOutputFile.toString(), Long.toString(Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS).getSeconds()))
+ .applyTo(cmd);
+
+ cmd.executeAndAssertImageCreated();
+
+ cmd.readLauncherCfgFile("probe")
+ .add(new CfgFile().addValue("Application", "win.norestart", Boolean.TRUE.toString()))
+ .save(cmd.appLauncherCfgPath("probe"));
+
+ // Try Ctrl+C signal on a launcher with disabled restart functionality.
+ // It will create a single launcher process instead of the parent and the child processes.
+ // Ctrl+C always worked for launcher with disabled restart functionality.
+ var probeOutput = runLauncher(cmd, "probe", probeTraceFile, probeOutputFile);
+
+ if (!probeOutput.equals("shutdown hook executed")) {
+ // Ctrl+C signal didn't make it. Test environment doesn't support Ctrl+C signal
+ // delivery from the prowershell process to a child process, don't run the main
+ // test.
+ TKit.throwSkippedException(
+ "The environment does NOT support Ctrl+C signal delivery from the prowershell process to a child process");
+ }
+
+ var mainOutput = runLauncher(cmd, null, mainTraceFile, mainOutputFile);
+
+ TKit.assertEquals("shutdown hook executed", mainOutput, "Check shutdown hook executed");
+ }
+
+ private static String runLauncher(JPackageCommand cmd, String launcherName, Path traceFile, Path outputFile) throws IOException {
+ // Launch the specified launcher and send Ctrl+C signal to it.
+ Thread.ofVirtual().start(() -> {
+ configureAndExecute(0, Executor.of("powershell", "-NonInteractive", "-NoLogo", "-NoProfile", "-ExecutionPolicy", "Unrestricted")
+ .addArgument("-File").addArgument(TEST_PS1)
+ .addArguments("-TimeoutSeconds", Long.toString(Duration.ofSeconds(5).getSeconds()))
+ .addArgument("-Executable").addArgument(cmd.appLauncherPath(launcherName))
+ .dumpOutput());
+ });
+
+ TKit.waitForFileCreated(traceFile, Duration.ofSeconds(20), Duration.ofSeconds(2));
+
+ try {
+ TKit.waitForFileCreated(outputFile, Duration.ofSeconds(TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS * 2), Duration.ofSeconds(2));
+ } finally {
+ TKit.traceFileContents(traceFile, "Test app trace");
+ }
+
+ TKit.assertFileExists(outputFile);
+ return Files.readString(outputFile);
+ }
+
+ private static final long TETS_APP_AUTOCLOSE_TIMEOUT_SECONDS = 30;
+
+ private static final Path TEST_APP_JAVA = TKit.TEST_SRC_ROOT.resolve("apps/UseShutdownHook.java");
+ private static final Path TEST_PS1 = TKit.TEST_SRC_ROOT.resolve(Path.of("resources/Win8365790Test.ps1")).normalize();
+}
From 0756ecb214b8ab76cb69f354063d153b72f978c2 Mon Sep 17 00:00:00 2001
From: Roger Riggs
Date: Wed, 17 Sep 2025 19:49:22 +0000
Subject: [PATCH 022/664] 8367031: [backout] Change java.time month/day field
types to 'byte'
Reviewed-by: alanb, liach, naoto, iris
---
.../share/classes/java/time/LocalDate.java | 8 ++++----
.../share/classes/java/time/MonthDay.java | 8 ++++----
.../share/classes/java/time/YearMonth.java | 4 ++--
.../share/classes/java/time/chrono/HijrahDate.java | 14 +++++++-------
4 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/java.base/share/classes/java/time/LocalDate.java b/src/java.base/share/classes/java/time/LocalDate.java
index 6724410da2b..016bdab5394 100644
--- a/src/java.base/share/classes/java/time/LocalDate.java
+++ b/src/java.base/share/classes/java/time/LocalDate.java
@@ -182,11 +182,11 @@ public final class LocalDate
/**
* @serial The month-of-year.
*/
- private final byte month;
+ private final short month;
/**
* @serial The day-of-month.
*/
- private final byte day;
+ private final short day;
//-----------------------------------------------------------------------
/**
@@ -490,8 +490,8 @@ public final class LocalDate
*/
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
- this.month = (byte) month;
- this.day = (byte) dayOfMonth;
+ this.month = (short) month;
+ this.day = (short) dayOfMonth;
}
//-----------------------------------------------------------------------
diff --git a/src/java.base/share/classes/java/time/MonthDay.java b/src/java.base/share/classes/java/time/MonthDay.java
index 6244c14e6e1..1de4fa84d3e 100644
--- a/src/java.base/share/classes/java/time/MonthDay.java
+++ b/src/java.base/share/classes/java/time/MonthDay.java
@@ -146,11 +146,11 @@ public final class MonthDay
/**
* @serial The month-of-year, not null.
*/
- private final byte month;
+ private final int month;
/**
* @serial The day-of-month.
*/
- private final byte day;
+ private final int day;
//-----------------------------------------------------------------------
/**
@@ -319,8 +319,8 @@ public final class MonthDay
* @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31
*/
private MonthDay(int month, int dayOfMonth) {
- this.month = (byte) month;
- this.day = (byte) dayOfMonth;
+ this.month = month;
+ this.day = dayOfMonth;
}
//-----------------------------------------------------------------------
diff --git a/src/java.base/share/classes/java/time/YearMonth.java b/src/java.base/share/classes/java/time/YearMonth.java
index b24151de3f0..8ad1172811f 100644
--- a/src/java.base/share/classes/java/time/YearMonth.java
+++ b/src/java.base/share/classes/java/time/YearMonth.java
@@ -153,7 +153,7 @@ public final class YearMonth
/**
* @serial The month-of-year, not null.
*/
- private final byte month;
+ private final int month;
//-----------------------------------------------------------------------
/**
@@ -306,7 +306,7 @@ public final class YearMonth
*/
private YearMonth(int year, int month) {
this.year = year;
- this.month = (byte) month;
+ this.month = month;
}
/**
diff --git a/src/java.base/share/classes/java/time/chrono/HijrahDate.java b/src/java.base/share/classes/java/time/chrono/HijrahDate.java
index 2d3e4f93e69..114a47e4797 100644
--- a/src/java.base/share/classes/java/time/chrono/HijrahDate.java
+++ b/src/java.base/share/classes/java/time/chrono/HijrahDate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -137,11 +137,11 @@ public final class HijrahDate
/**
* The month-of-year.
*/
- private final transient byte monthOfYear;
+ private final transient int monthOfYear;
/**
* The day-of-month.
*/
- private final transient byte dayOfMonth;
+ private final transient int dayOfMonth;
//-------------------------------------------------------------------------
/**
@@ -273,8 +273,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = prolepticYear;
- this.monthOfYear = (byte) monthOfYear;
- this.dayOfMonth = (byte) dayOfMonth;
+ this.monthOfYear = monthOfYear;
+ this.dayOfMonth = dayOfMonth;
}
/**
@@ -287,8 +287,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = dateInfo[0];
- this.monthOfYear = (byte) dateInfo[1];
- this.dayOfMonth = (byte) dateInfo[2];
+ this.monthOfYear = dateInfo[1];
+ this.dayOfMonth = dateInfo[2];
}
//-----------------------------------------------------------------------
From f682f070079037f8fb646e91ea336af0bc778813 Mon Sep 17 00:00:00 2001
From: Kim Barrett
Date: Wed, 17 Sep 2025 20:20:17 +0000
Subject: [PATCH 023/664] 8367796: Rename AtomicAccess gtests
Reviewed-by: ayang, tschatzl
---
.../gtest/runtime/test_atomicAccess.cpp | 103 +++++++++---------
1 file changed, 52 insertions(+), 51 deletions(-)
diff --git a/test/hotspot/gtest/runtime/test_atomicAccess.cpp b/test/hotspot/gtest/runtime/test_atomicAccess.cpp
index 523f27ca870..6e05f429970 100644
--- a/test/hotspot/gtest/runtime/test_atomicAccess.cpp
+++ b/test/hotspot/gtest/runtime/test_atomicAccess.cpp
@@ -25,13 +25,14 @@
#include "runtime/atomicAccess.hpp"
#include "unittest.hpp"
-// These tests of Atomic only verify functionality. They don't verify atomicity.
+// These tests of AtomicAccess only verify functionality. They don't verify
+// atomicity.
template
-struct AtomicAddTestSupport {
+struct AtomicAccessAddTestSupport {
volatile T _test_value;
- AtomicAddTestSupport() : _test_value{} {}
+ AtomicAccessAddTestSupport() : _test_value{} {}
void test_add() {
T zero = 0;
@@ -52,19 +53,19 @@ struct AtomicAddTestSupport {
}
};
-TEST_VM(AtomicAddTest, int32) {
- using Support = AtomicAddTestSupport;
+TEST_VM(AtomicAccessAddTest, int32) {
+ using Support = AtomicAccessAddTestSupport;
Support().test_add();
Support().test_fetch_add();
}
-TEST_VM(AtomicAddTest, int64) {
- using Support = AtomicAddTestSupport;
+TEST_VM(AtomicAccessAddTest, int64) {
+ using Support = AtomicAccessAddTestSupport;
Support().test_add();
Support().test_fetch_add();
}
-TEST_VM(AtomicAddTest, ptr) {
+TEST_VM(AtomicAccessAddTest, ptr) {
uint _test_values[10] = {};
uint* volatile _test_value{};
@@ -84,10 +85,10 @@ TEST_VM(AtomicAddTest, ptr) {
};
template
-struct AtomicXchgTestSupport {
+struct AtomicAccessXchgTestSupport {
volatile T _test_value;
- AtomicXchgTestSupport() : _test_value{} {}
+ AtomicAccessXchgTestSupport() : _test_value{} {}
void test() {
T zero = 0;
@@ -99,21 +100,21 @@ struct AtomicXchgTestSupport {
}
};
-TEST_VM(AtomicXchgTest, int32) {
- using Support = AtomicXchgTestSupport;
+TEST_VM(AtomicAccessXchgTest, int32) {
+ using Support = AtomicAccessXchgTestSupport;
Support().test();
}
-TEST_VM(AtomicXchgTest, int64) {
- using Support = AtomicXchgTestSupport;
+TEST_VM(AtomicAccessXchgTest, int64) {
+ using Support = AtomicAccessXchgTestSupport;
Support().test();
}
template
-struct AtomicCmpxchgTestSupport {
+struct AtomicAccessCmpxchgTestSupport {
volatile T _test_value;
- AtomicCmpxchgTestSupport() : _test_value{} {}
+ AtomicAccessCmpxchgTestSupport() : _test_value{} {}
void test() {
T zero = 0;
@@ -129,25 +130,25 @@ struct AtomicCmpxchgTestSupport {
}
};
-TEST_VM(AtomicCmpxchgTest, int32) {
- using Support = AtomicCmpxchgTestSupport;
+TEST_VM(AtomicAccessCmpxchgTest, int32) {
+ using Support = AtomicAccessCmpxchgTestSupport;
Support().test();
}
-TEST_VM(AtomicCmpxchgTest, int64) {
+TEST_VM(AtomicAccessCmpxchgTest, int64) {
// Check if 64-bit atomics are available on the machine.
if (!VM_Version::supports_cx8()) return;
- using Support = AtomicCmpxchgTestSupport;
+ using Support = AtomicAccessCmpxchgTestSupport;
Support().test();
}
-struct AtomicCmpxchg1ByteStressSupport {
+struct AtomicAccessCmpxchg1ByteStressSupport {
char _default_val;
int _base;
char _array[7+32+7];
- AtomicCmpxchg1ByteStressSupport() : _default_val(0x7a), _base(7), _array{} {}
+ AtomicAccessCmpxchg1ByteStressSupport() : _default_val(0x7a), _base(7), _array{} {}
void validate(char val, char val2, int index) {
for (int i = 0; i < 7; i++) {
@@ -182,16 +183,16 @@ struct AtomicCmpxchg1ByteStressSupport {
}
};
-TEST_VM(AtomicCmpxchg1Byte, stress) {
- AtomicCmpxchg1ByteStressSupport support;
+TEST_VM(AtomicAccessCmpxchg1Byte, stress) {
+ AtomicAccessCmpxchg1ByteStressSupport support;
support.test();
}
template
-struct AtomicEnumTestSupport {
+struct AtomicAccessEnumTestSupport {
volatile T _test_value;
- AtomicEnumTestSupport() : _test_value{} {}
+ AtomicAccessEnumTestSupport() : _test_value{} {}
void test_store_load(T value) {
EXPECT_NE(value, AtomicAccess::load(&_test_value));
@@ -216,25 +217,25 @@ struct AtomicEnumTestSupport {
}
};
-namespace AtomicEnumTestUnscoped { // Scope the enumerators.
+namespace AtomicAccessEnumTestUnscoped { // Scope the enumerators.
enum TestEnum { A, B, C };
}
-TEST_VM(AtomicEnumTest, unscoped_enum) {
- using namespace AtomicEnumTestUnscoped;
- using Support = AtomicEnumTestSupport;
+TEST_VM(AtomicAccessEnumTest, unscoped_enum) {
+ using namespace AtomicAccessEnumTestUnscoped;
+ using Support = AtomicAccessEnumTestSupport;
Support().test_store_load(B);
Support().test_cmpxchg(B, C);
Support().test_xchg(B, C);
}
-enum class AtomicEnumTestScoped { A, B, C };
+enum class AtomicAccessEnumTestScoped { A, B, C };
-TEST_VM(AtomicEnumTest, scoped_enum) {
- const AtomicEnumTestScoped B = AtomicEnumTestScoped::B;
- const AtomicEnumTestScoped C = AtomicEnumTestScoped::C;
- using Support = AtomicEnumTestSupport;
+TEST_VM(AtomicAccessEnumTest, scoped_enum) {
+ const AtomicAccessEnumTestScoped B = AtomicAccessEnumTestScoped::B;
+ const AtomicAccessEnumTestScoped C = AtomicAccessEnumTestScoped::C;
+ using Support = AtomicAccessEnumTestSupport;
Support().test_store_load(B);
Support().test_cmpxchg(B, C);
@@ -242,14 +243,14 @@ TEST_VM(AtomicEnumTest, scoped_enum) {
}
template
-struct AtomicBitopsTestSupport {
+struct AtomicAccessBitopsTestSupport {
volatile T _test_value;
// At least one byte differs between _old_value and _old_value op _change_value.
static const T _old_value = static_cast(UCONST64(0x7f5300007f530044));
static const T _change_value = static_cast(UCONST64(0x3800530038005322));
- AtomicBitopsTestSupport() : _test_value(0) {}
+ AtomicAccessBitopsTestSupport() : _test_value(0) {}
void fetch_then_and() {
AtomicAccess::store(&_test_value, _old_value);
@@ -320,31 +321,31 @@ struct AtomicBitopsTestSupport {
};
template
-const T AtomicBitopsTestSupport::_old_value;
+const T AtomicAccessBitopsTestSupport::_old_value;
template
-const T AtomicBitopsTestSupport::_change_value;
+const T AtomicAccessBitopsTestSupport::_change_value;
-TEST_VM(AtomicBitopsTest, int8) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, int8) {
+ AtomicAccessBitopsTestSupport()();
}
-TEST_VM(AtomicBitopsTest, uint8) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, uint8) {
+ AtomicAccessBitopsTestSupport()();
}
-TEST_VM(AtomicBitopsTest, int32) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, int32) {
+ AtomicAccessBitopsTestSupport()();
}
-TEST_VM(AtomicBitopsTest, uint32) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, uint32) {
+ AtomicAccessBitopsTestSupport()();
}
-TEST_VM(AtomicBitopsTest, int64) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, int64) {
+ AtomicAccessBitopsTestSupport()();
}
-TEST_VM(AtomicBitopsTest, uint64) {
- AtomicBitopsTestSupport()();
+TEST_VM(AtomicAccessBitopsTest, uint64) {
+ AtomicAccessBitopsTestSupport()();
}
From 919f5faa4618473eddab39d65fe7c1cc732600b7 Mon Sep 17 00:00:00 2001
From: Joe Darcy
Date: Wed, 17 Sep 2025 20:47:11 +0000
Subject: [PATCH 024/664] 8367787: Expand use of representation equivalence
terminology in Float16
Reviewed-by: psandoz
---
.../share/classes/jdk/incubator/vector/Float16.java | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java
index 5d6a4bbfecb..3202ca2ba25 100644
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java
@@ -890,7 +890,9 @@ public final class Float16
* is {@code true} if and only if the argument is not
* {@code null} and is a {@code Float16} object that
* represents a {@code Float16} that has the same value as the
- * {@code double} represented by this object.
+ * {@code Float16} represented by this object.
+ * {@linkplain Double##repEquivalence Representation
+ * equivalence} is used to compare the {@code Float16} values.
*
* @jls 15.21.1 Numerical Equality Operators == and !=
*/
@@ -988,6 +990,13 @@ public final class Float16
/**
* Compares the two specified {@code Float16} values.
*
+ * @apiNote
+ * One idiom to implement {@linkplain Double##repEquivalence
+ * representation equivalence} on {@code Float16} values is
+ * {@snippet lang="java" :
+ * Float16.compare(a, b) == 0
+ * }
+ *
* @param f1 the first {@code Float16} to compare
* @param f2 the second {@code Float16} to compare
* @return the value {@code 0} if {@code f1} is
From aa36799acb5834d730400fb073a9a3a8ee3c28ef Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Wed, 17 Sep 2025 21:34:15 +0000
Subject: [PATCH 025/664] 8367333: C2: Vector math operation intrinsification
failure
Reviewed-by: epeter, shade, jbhateja
---
src/hotspot/share/prims/vectorSupport.cpp | 19 +++
src/hotspot/share/prims/vectorSupport.hpp | 19 +++
.../compiler/vectorapi/TestVectorMathLib.java | 129 ++++++++++++++++++
3 files changed, 167 insertions(+)
create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp
index 002f737e788..a98cad07227 100644
--- a/src/hotspot/share/prims/vectorSupport.cpp
+++ b/src/hotspot/share/prims/vectorSupport.cpp
@@ -592,6 +592,25 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) {
break;
}
+ case VECTOR_OP_TAN: // fall-through
+ case VECTOR_OP_TANH: // fall-through
+ case VECTOR_OP_SIN: // fall-through
+ case VECTOR_OP_SINH: // fall-through
+ case VECTOR_OP_COS: // fall-through
+ case VECTOR_OP_COSH: // fall-through
+ case VECTOR_OP_ASIN: // fall-through
+ case VECTOR_OP_ACOS: // fall-through
+ case VECTOR_OP_ATAN: // fall-through
+ case VECTOR_OP_ATAN2: // fall-through
+ case VECTOR_OP_CBRT: // fall-through
+ case VECTOR_OP_LOG: // fall-through
+ case VECTOR_OP_LOG10: // fall-through
+ case VECTOR_OP_LOG1P: // fall-through
+ case VECTOR_OP_POW: // fall-through
+ case VECTOR_OP_EXP: // fall-through
+ case VECTOR_OP_EXPM1: // fall-through
+ case VECTOR_OP_HYPOT: return 0; // not supported; should be handled in Java code
+
default: fatal("unknown op: %d", vop);
}
return 0; // Unimplemented
diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp
index 5ba18cdfaa8..9ec6500543c 100644
--- a/src/hotspot/share/prims/vectorSupport.hpp
+++ b/src/hotspot/share/prims/vectorSupport.hpp
@@ -101,6 +101,25 @@ class VectorSupport : AllStatic {
VECTOR_OP_COMPRESS_BITS = 33,
VECTOR_OP_EXPAND_BITS = 34,
+ VECTOR_OP_TAN = 101,
+ VECTOR_OP_TANH = 102,
+ VECTOR_OP_SIN = 103,
+ VECTOR_OP_SINH = 104,
+ VECTOR_OP_COS = 105,
+ VECTOR_OP_COSH = 106,
+ VECTOR_OP_ASIN = 107,
+ VECTOR_OP_ACOS = 108,
+ VECTOR_OP_ATAN = 109,
+ VECTOR_OP_ATAN2 = 110,
+ VECTOR_OP_CBRT = 111,
+ VECTOR_OP_LOG = 112,
+ VECTOR_OP_LOG10 = 113,
+ VECTOR_OP_LOG1P = 114,
+ VECTOR_OP_POW = 115,
+ VECTOR_OP_EXP = 116,
+ VECTOR_OP_EXPM1 = 117,
+ VECTOR_OP_HYPOT = 118,
+
VECTOR_OP_SADD = 119,
VECTOR_OP_SSUB = 120,
VECTOR_OP_SUADD = 121,
diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
new file mode 100644
index 00000000000..112220262b6
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2025, 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 compiler.vectorapi;
+
+import jdk.incubator.vector.FloatVector;
+import jdk.incubator.vector.VectorOperators;
+import jdk.incubator.vector.VectorSpecies;
+
+/*
+ * @test
+ * @bug 8367333
+ * @requires vm.compiler2.enabled
+ * @modules jdk.incubator.vector
+ * @library /test/lib
+ *
+ * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:+StressIncrementalInlining -XX:CompileCommand=quiet
+ * -XX:CompileCommand=compileonly,compiler.vectorapi.TestVectorMathLib::test*
+ * compiler.vectorapi.TestVectorMathLib
+ */
+
+public class TestVectorMathLib {
+ private static final VectorSpecies SPECIES = FloatVector.SPECIES_PREFERRED;
+
+ static FloatVector testTAN(FloatVector fv) {
+ return fv.lanewise(VectorOperators.TAN);
+ }
+ static FloatVector testTANH(FloatVector fv) {
+ return fv.lanewise(VectorOperators.TANH);
+ }
+ static FloatVector testSIN(FloatVector fv) {
+ return fv.lanewise(VectorOperators.SIN);
+ }
+ static FloatVector testSINH(FloatVector fv) {
+ return fv.lanewise(VectorOperators.SINH);
+ }
+ static FloatVector testCOS(FloatVector fv) {
+ return fv.lanewise(VectorOperators.COS);
+ }
+ static FloatVector testCOSH(FloatVector fv) {
+ return fv.lanewise(VectorOperators.COSH);
+ }
+ static FloatVector testASIN(FloatVector fv) {
+ return fv.lanewise(VectorOperators.ASIN);
+ }
+ static FloatVector testACOS(FloatVector fv) {
+ return fv.lanewise(VectorOperators.ACOS);
+ }
+ static FloatVector testATAN(FloatVector fv) {
+ return fv.lanewise(VectorOperators.ATAN);
+ }
+ static FloatVector testATAN2(FloatVector fv) {
+ return fv.lanewise(VectorOperators.ATAN2, fv);
+ }
+ static FloatVector testCBRT(FloatVector fv) {
+ return fv.lanewise(VectorOperators.CBRT);
+ }
+ static FloatVector testLOG(FloatVector fv) {
+ return fv.lanewise(VectorOperators.LOG);
+ }
+ static FloatVector testLOG10(FloatVector fv) {
+ return fv.lanewise(VectorOperators.LOG10);
+ }
+ static FloatVector testLOG1P(FloatVector fv) {
+ return fv.lanewise(VectorOperators.LOG1P);
+ }
+ static FloatVector testPOW(FloatVector fv) {
+ return fv.lanewise(VectorOperators.POW, fv);
+ }
+ static FloatVector testEXP(FloatVector fv) {
+ return fv.lanewise(VectorOperators.EXP);
+ }
+ static FloatVector testEXPM1(FloatVector fv) {
+ return fv.lanewise(VectorOperators.EXPM1);
+ }
+ static FloatVector testHYPOT(FloatVector fv) {
+ return fv.lanewise(VectorOperators.HYPOT, fv);
+ }
+
+ public static void main(String[] args) {
+ FloatVector z = FloatVector.zero(SPECIES);
+ for (int i = 0; i < 20_000; i++) {
+ z.neg(); // unary
+ z.add(z); // binary
+
+ testTAN(z);
+ testTANH(z);
+ testSIN(z);
+ testSINH(z);
+ testCOS(z);
+ testCOSH(z);
+ testASIN(z);
+ testACOS(z);
+ testATAN(z);
+ testATAN2(z);
+ testCBRT(z);
+ testLOG(z);
+ testLOG10(z);
+ testLOG1P(z);
+ testPOW(z);
+ testEXP(z);
+ testEXPM1(z);
+ testHYPOT(z);
+ }
+
+ System.out.println("TEST PASSED");
+ }
+}
+
From 91a979430e2516b5853c397a336837799928f478 Mon Sep 17 00:00:00 2001
From: Ioi Lam
Date: Thu, 18 Sep 2025 02:49:10 +0000
Subject: [PATCH 026/664] 8367366: Do not support -XX:+AOTClassLinking for
dynamic CDS archive
Reviewed-by: kvn, asmehra
---
src/hotspot/share/cds/aotClassLinker.cpp | 13 ++---------
.../share/cds/aotLinkedClassBulkLoader.cpp | 22 ++++++++-----------
.../share/cds/aotLinkedClassBulkLoader.hpp | 2 +-
src/hotspot/share/cds/aotLinkedClassTable.cpp | 3 +--
src/hotspot/share/cds/aotLinkedClassTable.hpp | 12 +++-------
src/hotspot/share/cds/aotMetaspace.cpp | 4 ++--
src/hotspot/share/cds/archiveBuilder.cpp | 8 -------
src/hotspot/share/cds/archiveBuilder.hpp | 1 -
src/hotspot/share/cds/cdsConfig.cpp | 16 +++++++++-----
src/hotspot/share/cds/dynamicArchive.cpp | 13 ++++++-----
src/hotspot/share/cds/dynamicArchive.hpp | 2 +-
.../classfile/systemDictionaryShared.cpp | 5 -----
test/hotspot/jtreg/TEST.groups | 12 +---------
.../aotClassLinking/BulkLoaderTest.java | 18 ---------------
.../resolvedConstants/ResolvedConstants.java | 4 +++-
15 files changed, 41 insertions(+), 94 deletions(-)
diff --git a/src/hotspot/share/cds/aotClassLinker.cpp b/src/hotspot/share/cds/aotClassLinker.cpp
index 1f9a03de83f..0eb8f141c20 100644
--- a/src/hotspot/share/cds/aotClassLinker.cpp
+++ b/src/hotspot/share/cds/aotClassLinker.cpp
@@ -191,7 +191,7 @@ void AOTClassLinker::write_to_archive() {
assert_at_safepoint();
if (CDSConfig::is_dumping_aot_linked_classes()) {
- AOTLinkedClassTable* table = AOTLinkedClassTable::get(CDSConfig::is_dumping_static_archive());
+ AOTLinkedClassTable* table = AOTLinkedClassTable::get();
table->set_boot(write_classes(nullptr, true));
table->set_boot2(write_classes(nullptr, false));
table->set_platform(write_classes(SystemDictionary::java_platform_loader(), false));
@@ -212,16 +212,7 @@ Array* AOTClassLinker::write_classes(oop class_loader, bool is_j
continue;
}
- if (ik->in_aot_cache() && CDSConfig::is_dumping_dynamic_archive()) {
- if (CDSConfig::is_using_aot_linked_classes()) {
- // This class was recorded as AOT-linked for the base archive,
- // so there's no need to do so again for the dynamic archive.
- } else {
- list.append(ik);
- }
- } else {
- list.append(ArchiveBuilder::current()->get_buffered_addr(ik));
- }
+ list.append(ArchiveBuilder::current()->get_buffered_addr(ik));
}
if (list.length() == 0) {
diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp
index 6e5816cd589..8795a29fd5c 100644
--- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp
+++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp
@@ -46,8 +46,8 @@ bool AOTLinkedClassBulkLoader::_platform_completed = false;
bool AOTLinkedClassBulkLoader::_app_completed = false;
bool AOTLinkedClassBulkLoader::_all_completed = false;
-void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc, bool is_static_archive) {
- AOTLinkedClassTable::get(is_static_archive)->serialize(soc);
+void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc) {
+ AOTLinkedClassTable::get()->serialize(soc);
}
bool AOTLinkedClassBulkLoader::class_preloading_finished() {
@@ -117,27 +117,24 @@ void AOTLinkedClassBulkLoader::exit_on_exception(JavaThread* current) {
void AOTLinkedClassBulkLoader::load_classes_in_loader_impl(AOTLinkedClassCategory class_category, oop class_loader_oop, TRAPS) {
Handle h_loader(THREAD, class_loader_oop);
- load_table(AOTLinkedClassTable::for_static_archive(), class_category, h_loader, CHECK);
- load_table(AOTLinkedClassTable::for_dynamic_archive(), class_category, h_loader, CHECK);
+ AOTLinkedClassTable* table = AOTLinkedClassTable::get();
+ load_table(table, class_category, h_loader, CHECK);
// Initialize the InstanceKlasses of all archived heap objects that are reachable from the
// archived java class mirrors.
- //
- // Only the classes in the static archive can have archived mirrors.
- AOTLinkedClassTable* static_table = AOTLinkedClassTable::for_static_archive();
switch (class_category) {
case AOTLinkedClassCategory::BOOT1:
// Delayed until finish_loading_javabase_classes(), as the VM is not ready to
// execute some of the methods.
break;
case AOTLinkedClassCategory::BOOT2:
- init_required_classes_for_loader(h_loader, static_table->boot2(), CHECK);
+ init_required_classes_for_loader(h_loader, table->boot2(), CHECK);
break;
case AOTLinkedClassCategory::PLATFORM:
- init_required_classes_for_loader(h_loader, static_table->platform(), CHECK);
+ init_required_classes_for_loader(h_loader, table->platform(), CHECK);
break;
case AOTLinkedClassCategory::APP:
- init_required_classes_for_loader(h_loader, static_table->app(), CHECK);
+ init_required_classes_for_loader(h_loader, table->app(), CHECK);
break;
case AOTLinkedClassCategory::UNREGISTERED:
ShouldNotReachHere();
@@ -333,7 +330,7 @@ void AOTLinkedClassBulkLoader::load_hidden_class(ClassLoaderData* loader_data, I
}
void AOTLinkedClassBulkLoader::finish_loading_javabase_classes(TRAPS) {
- init_required_classes_for_loader(Handle(), AOTLinkedClassTable::for_static_archive()->boot(), CHECK);
+ init_required_classes_for_loader(Handle(), AOTLinkedClassTable::get()->boot(), CHECK);
}
// Some AOT-linked classes for must be initialized early. This includes
@@ -427,8 +424,7 @@ void AOTLinkedClassBulkLoader::replay_training_at_init(Array* cl
void AOTLinkedClassBulkLoader::replay_training_at_init_for_preloaded_classes(TRAPS) {
if (CDSConfig::is_using_aot_linked_classes() && TrainingData::have_data()) {
- // Only static archive can have training data.
- AOTLinkedClassTable* table = AOTLinkedClassTable::for_static_archive();
+ AOTLinkedClassTable* table = AOTLinkedClassTable::get();
replay_training_at_init(table->boot(), CHECK);
replay_training_at_init(table->boot2(), CHECK);
replay_training_at_init(table->platform(), CHECK);
diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp
index 0a8b0c4d537..95e64a7ddd4 100644
--- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp
+++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp
@@ -57,7 +57,7 @@ class AOTLinkedClassBulkLoader : AllStatic {
static void init_required_classes_for_loader(Handle class_loader, Array* classes, TRAPS);
static void replay_training_at_init(Array* classes, TRAPS) NOT_CDS_RETURN;
public:
- static void serialize(SerializeClosure* soc, bool is_static_archive) NOT_CDS_RETURN;
+ static void serialize(SerializeClosure* soc) NOT_CDS_RETURN;
static void load_javabase_classes(JavaThread* current) NOT_CDS_RETURN;
static void load_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN;
diff --git a/src/hotspot/share/cds/aotLinkedClassTable.cpp b/src/hotspot/share/cds/aotLinkedClassTable.cpp
index b602c599f54..79d78b05be1 100644
--- a/src/hotspot/share/cds/aotLinkedClassTable.cpp
+++ b/src/hotspot/share/cds/aotLinkedClassTable.cpp
@@ -27,8 +27,7 @@
#include "cds/serializeClosure.hpp"
#include "oops/array.hpp"
-AOTLinkedClassTable AOTLinkedClassTable::_for_static_archive;
-AOTLinkedClassTable AOTLinkedClassTable::_for_dynamic_archive;
+AOTLinkedClassTable AOTLinkedClassTable::_instance;
void AOTLinkedClassTable::serialize(SerializeClosure* soc) {
soc->do_ptr((void**)&_boot);
diff --git a/src/hotspot/share/cds/aotLinkedClassTable.hpp b/src/hotspot/share/cds/aotLinkedClassTable.hpp
index 2a199c15edd..0ec733d1df7 100644
--- a/src/hotspot/share/cds/aotLinkedClassTable.hpp
+++ b/src/hotspot/share/cds/aotLinkedClassTable.hpp
@@ -39,10 +39,7 @@ class SerializeClosure;
// in a production run.
//
class AOTLinkedClassTable {
- // The VM may load up to 2 CDS archives -- static and dynamic. Each
- // archive can have its own AOTLinkedClassTable.
- static AOTLinkedClassTable _for_static_archive;
- static AOTLinkedClassTable _for_dynamic_archive;
+ static AOTLinkedClassTable _instance;
Array* _boot; // only java.base classes
Array* _boot2; // boot classes in other modules
@@ -54,11 +51,8 @@ public:
_boot(nullptr), _boot2(nullptr),
_platform(nullptr), _app(nullptr) {}
- static AOTLinkedClassTable* for_static_archive() { return &_for_static_archive; }
- static AOTLinkedClassTable* for_dynamic_archive() { return &_for_dynamic_archive; }
-
- static AOTLinkedClassTable* get(bool is_static_archive) {
- return is_static_archive ? for_static_archive() : for_dynamic_archive();
+ static AOTLinkedClassTable* get() {
+ return &_instance;
}
Array* boot() const { return _boot; }
diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp
index b3f859fc4a8..341371ad6bc 100644
--- a/src/hotspot/share/cds/aotMetaspace.cpp
+++ b/src/hotspot/share/cds/aotMetaspace.cpp
@@ -501,7 +501,7 @@ void AOTMetaspace::serialize(SerializeClosure* soc) {
StringTable::serialize_shared_table_header(soc);
HeapShared::serialize_tables(soc);
SystemDictionaryShared::serialize_dictionary_headers(soc);
- AOTLinkedClassBulkLoader::serialize(soc, true);
+ AOTLinkedClassBulkLoader::serialize(soc);
FinalImageRecipes::serialize(soc);
TrainingData::serialize(soc);
InstanceMirrorKlass::serialize_offsets(soc);
@@ -2001,7 +2001,7 @@ void AOTMetaspace::initialize_shared_spaces() {
if (dynamic_mapinfo != nullptr) {
intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data();
ReadClosure rc(&buffer, (intptr_t)SharedBaseAddress);
- ArchiveBuilder::serialize_dynamic_archivable_items(&rc);
+ DynamicArchive::serialize(&rc);
DynamicArchive::setup_array_klasses();
}
diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
index 77f51443bb2..41a1d3d3c6d 100644
--- a/src/hotspot/share/cds/archiveBuilder.cpp
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
@@ -24,7 +24,6 @@
#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassLinker.hpp"
-#include "cds/aotLinkedClassBulkLoader.hpp"
#include "cds/aotLogging.hpp"
#include "cds/aotMapLogger.hpp"
#include "cds/aotMetaspace.hpp"
@@ -1015,13 +1014,6 @@ void ArchiveBuilder::make_training_data_shareable() {
_src_obj_table.iterate_all(clean_td);
}
-void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
- SymbolTable::serialize_shared_table_header(soc, false);
- SystemDictionaryShared::serialize_dictionary_headers(soc, false);
- DynamicArchive::serialize_array_klasses(soc);
- AOTLinkedClassBulkLoader::serialize(soc, false);
-}
-
uintx ArchiveBuilder::buffer_to_offset(address p) const {
address requested_p = to_requested(p);
assert(requested_p >= _requested_static_archive_bottom, "must be");
diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp
index 170e61beba8..815a6f07273 100644
--- a/src/hotspot/share/cds/archiveBuilder.hpp
+++ b/src/hotspot/share/cds/archiveBuilder.hpp
@@ -382,7 +382,6 @@ public:
bool gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool read_only);
bool gather_one_source_obj(MetaspaceClosure::Ref* ref, bool read_only);
void remember_embedded_pointer_in_enclosing_obj(MetaspaceClosure::Ref* ref);
- static void serialize_dynamic_archivable_items(SerializeClosure* soc);
DumpRegion* pz_region() { return &_pz_region; }
DumpRegion* rw_region() { return &_rw_region; }
diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp
index 0505ae20a78..20bf6b0d67c 100644
--- a/src/hotspot/share/cds/cdsConfig.cpp
+++ b/src/hotspot/share/cds/cdsConfig.cpp
@@ -756,6 +756,13 @@ void CDSConfig::setup_compiler_args() {
void CDSConfig::prepare_for_dumping() {
assert(CDSConfig::is_dumping_archive(), "sanity");
+ if (is_dumping_dynamic_archive() && AOTClassLinking) {
+ if (FLAG_IS_CMDLINE(AOTClassLinking)) {
+ log_warning(cds)("AOTClassLinking is not supported for dynamic CDS archive");
+ }
+ FLAG_SET_ERGO(AOTClassLinking, false);
+ }
+
if (is_dumping_dynamic_archive() && !is_using_archive()) {
assert(!is_dumping_static_archive(), "cannot be dumping both static and dynamic archives");
@@ -1014,11 +1021,10 @@ void CDSConfig::stop_using_full_module_graph(const char* reason) {
}
bool CDSConfig::is_dumping_aot_linked_classes() {
- if (is_dumping_preimage_static_archive()) {
- return false;
- } else if (is_dumping_dynamic_archive()) {
- return is_using_full_module_graph() && AOTClassLinking;
- } else if (is_dumping_static_archive()) {
+ if (is_dumping_classic_static_archive() || is_dumping_final_static_archive()) {
+ // FMG is required to guarantee that all cached boot/platform/app classes
+ // are visible in the production run, so they can be unconditionally
+ // loaded during VM bootstrap.
return is_dumping_full_module_graph() && AOTClassLinking;
} else {
return false;
diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp
index 58b354b9240..0ba911b41bb 100644
--- a/src/hotspot/share/cds/dynamicArchive.cpp
+++ b/src/hotspot/share/cds/dynamicArchive.cpp
@@ -160,11 +160,10 @@ public:
SystemDictionaryShared::write_to_archive(false);
cl_config = AOTClassLocationConfig::dumptime()->write_to_archive();
DynamicArchive::dump_array_klasses();
- AOTClassLinker::write_to_archive();
serialized_data = ro_region()->top();
WriteClosure wc(ro_region());
- ArchiveBuilder::serialize_dynamic_archivable_items(&wc);
+ DynamicArchive::serialize(&wc);
}
if (CDSConfig::is_dumping_lambdas_in_legacy_mode()) {
@@ -414,6 +413,12 @@ public:
GrowableArray* DynamicArchive::_array_klasses = nullptr;
Array* DynamicArchive::_dynamic_archive_array_klasses = nullptr;
+void DynamicArchive::serialize(SerializeClosure* soc) {
+ SymbolTable::serialize_shared_table_header(soc, false);
+ SystemDictionaryShared::serialize_dictionary_headers(soc, false);
+ soc->do_ptr(&_dynamic_archive_array_klasses);
+}
+
void DynamicArchive::append_array_klass(ObjArrayKlass* ak) {
if (_array_klasses == nullptr) {
_array_klasses = new (mtClassShared) GrowableArray(50, mtClassShared);
@@ -456,10 +461,6 @@ void DynamicArchive::setup_array_klasses() {
}
}
-void DynamicArchive::serialize_array_klasses(SerializeClosure* soc) {
- soc->do_ptr(&_dynamic_archive_array_klasses);
-}
-
void DynamicArchive::make_array_klasses_shareable() {
if (_array_klasses != nullptr) {
int num_array_klasses = _array_klasses->length();
diff --git a/src/hotspot/share/cds/dynamicArchive.hpp b/src/hotspot/share/cds/dynamicArchive.hpp
index 19086053d76..c42c4b7dfde 100644
--- a/src/hotspot/share/cds/dynamicArchive.hpp
+++ b/src/hotspot/share/cds/dynamicArchive.hpp
@@ -71,7 +71,7 @@ public:
static void dump_array_klasses();
static void setup_array_klasses();
static void append_array_klass(ObjArrayKlass* oak);
- static void serialize_array_klasses(SerializeClosure* soc);
+ static void serialize(SerializeClosure* soc);
static void make_array_klasses_shareable();
static void post_dump();
static int num_array_klasses();
diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp
index eda823704ca..513ebe8bb84 100644
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp
@@ -867,11 +867,6 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) {
} else {
InstanceKlass* ik = InstanceKlass::cast(k);
- if (CDSConfig::is_dumping_dynamic_archive() && ik->in_aot_cache()) {
- // ik is already part of the static archive, so it will never be considered as excluded.
- return false;
- }
-
if (!SafepointSynchronize::is_at_safepoint()) {
if (!ik->is_linked()) {
// should_be_excluded_impl() below doesn't link unlinked classes. We come
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index 3af6548fe33..18cd93d4856 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -534,17 +534,7 @@ hotspot_aot_classlinking = \
-runtime/cds/appcds/customLoader/ParallelTestSingleFP.java \
-runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java \
-runtime/cds/appcds/DumpClassListWithLF.java \
- -runtime/cds/appcds/dynamicArchive/LambdaContainsOldInf.java \
- -runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java \
- -runtime/cds/appcds/dynamicArchive/LambdaForOldInfInBaseArchive.java \
- -runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java \
- -runtime/cds/appcds/dynamicArchive/LambdasInTwoArchives.java \
- -runtime/cds/appcds/dynamicArchive/ModulePath.java \
- -runtime/cds/appcds/dynamicArchive/NestHostOldInf.java \
- -runtime/cds/appcds/dynamicArchive/OldClassAndInf.java \
- -runtime/cds/appcds/dynamicArchive/OldClassInBaseArchive.java \
- -runtime/cds/appcds/dynamicArchive/OldClassVerifierTrouble.java \
- -runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java \
+ -runtime/cds/appcds/dynamicArchive \
-runtime/cds/appcds/HelloExtTest.java \
-runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java \
-runtime/cds/appcds/javaldr/GCDuringDump.java \
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
index e1f5f548593..9e43d00e872 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
@@ -40,20 +40,6 @@
* @run driver BulkLoaderTest STATIC
*/
-/*
- * @test id=dynamic
- * @requires vm.cds.supports.aot.class.linking
- * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @build InitiatingLoaderTester BadOldClassA BadOldClassB
- * @build jdk.test.whitebox.WhiteBox BulkLoaderTest SimpleCusty
- * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester
- * BadOldClassA BadOldClassB
- * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar
- * SimpleCusty
- * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:WhiteBox.jar BulkLoaderTest DYNAMIC
- */
-
/*
* @test id=aot
* @requires vm.cds.supports.aot.class.linking
@@ -279,10 +265,6 @@ class BulkLoaderTestApp {
}
try {
- // In dynamic dump, the VM loads BadOldClassB and then attempts to
- // link it. This will leave BadOldClassB in a "failed verification" state.
- // All refernces to BadOldClassB from the CP should be purged from the CDS
- // archive.
c = BadOldClassB.class;
c.newInstance();
throw new RuntimeException("Must not succeed");
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java
index 2610dac16c0..bc2ac9db2ab 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java
@@ -73,7 +73,9 @@ public class ResolvedConstants {
static boolean aotClassLinking;
public static void main(String[] args) throws Exception {
test(args, false);
- test(args, true);
+ if (!args[0].equals("DYNAMIC")) {
+ test(args, true);
+ }
}
static void test(String[] args, boolean testMode) throws Exception {
From a355edbbe43f7356f9439ecabf0ab8218fc9e3e1 Mon Sep 17 00:00:00 2001
From: Damon Fenacci
Date: Thu, 18 Sep 2025 06:24:49 +0000
Subject: [PATCH 027/664] 8367278: Test compiler/startup/StartupOutput.java
timed out after completion on Windows
Reviewed-by: syan, chagedorn
---
test/hotspot/jtreg/compiler/startup/StartupOutput.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
index 14897f7ab87..bb08a2c0a2d 100644
--- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java
+++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
@@ -64,7 +64,7 @@ public class StartupOutput {
// On s390x, generated code is ~6x larger in fastdebug and ~1.4x in release builds vs. other archs,
// hence we require slightly more minimum space.
int minInitialSize = 800 + (Platform.isS390x() ? 800 : 0);
- for (int i = 0; i < 200; i++) {
+ for (int i = 0; i < 50; i++) {
int initialCodeCacheSizeInKb = minInitialSize + rand.nextInt(400);
int reservedCodeCacheSizeInKb = initialCodeCacheSizeInKb + rand.nextInt(200);
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:InitialCodeCacheSize=" + initialCodeCacheSizeInKb + "K", "-XX:ReservedCodeCacheSize=" + reservedCodeCacheSizeInKb + "k", "-version");
From a306f88a8456be454f4954c7e4fb8a1273344b5b Mon Sep 17 00:00:00 2001
From: Srinivas Mandalika
Date: Thu, 18 Sep 2025 06:41:20 +0000
Subject: [PATCH 028/664] 8339791: Refactor
MiscUndecorated/ActiveAWTWindowTest.java
Reviewed-by: psadhukhan
---
.../MiscUndecorated/ActiveAWTWindowTest.java | 207 ++++++------------
1 file changed, 72 insertions(+), 135 deletions(-)
diff --git a/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java b/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java
index c7ec6c6d969..aabaf0b511b 100644
--- a/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java
+++ b/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java
@@ -24,18 +24,22 @@
/*
* @test
* @key headful
- * @summary To check proper WINDOW_EVENTS are triggered when Frame gains or losses the focus
- * @library /lib/client
- * @build ExtendedRobot
+ * @summary To check proper WINDOW_EVENTS are triggered when Frame gains
+ * or loses the focus
* @run main ActiveAWTWindowTest
*/
+import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Frame;
+import java.awt.Point;
+import java.awt.Robot;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -43,101 +47,74 @@ import java.awt.event.InputEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
public class ActiveAWTWindowTest {
- private Frame frame, frame2;
- private Button button, button2;
- private TextField textField, textField2;
- private volatile int eventType;
- private final Object lock1 = new Object();
- private final Object lock2 = new Object();
- private final Object lock3 = new Object();
- private boolean passed = true;
- private final int delay = 150;
+ private static Frame frame, frame2;
+ private static Button button, button2;
+ private static TextField textField, textField2;
+
+ private static CountDownLatch windowActivatedLatch = new CountDownLatch(1);
+ private static CountDownLatch windowDeactivatedLatch = new CountDownLatch(1);
+ private static CountDownLatch windowFocusGainedLatch = new CountDownLatch(1);
public static void main(String[] args) throws Exception {
- ActiveAWTWindowTest test = new ActiveAWTWindowTest();
- try {
- test.doTest();
- } finally {
- EventQueue.invokeAndWait(() -> {
- if (test.frame != null) {
- test.frame.dispose();
- }
- if (test.frame2 != null) {
- test.frame2.dispose();
- }
- });
- }
+ EventQueue.invokeAndWait(() -> {
+ initializeGUI();
+ });
+ doTest();
+ EventQueue.invokeAndWait(() -> {
+ if (frame != null) {
+ frame.dispose();
+ }
+ if (frame2 != null) {
+ frame2.dispose();
+ }
+ });
}
- public ActiveAWTWindowTest() {
- try{
- EventQueue.invokeAndWait( () -> {
- initializeGUI();
- });
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException("Interrupted or unexpected Exception occured");
- }
- }
-
- private void initializeGUI() {
+ private static void initializeGUI() {
frame = new Frame();
frame.setLayout(new FlowLayout());
-
frame.setLocation(5, 20);
frame.setSize(200, 200);
frame.setUndecorated(true);
+
frame.addWindowFocusListener(new WindowFocusListener() {
+ @Override
public void windowGainedFocus(WindowEvent event) {
System.out.println("Frame Focus gained");
- synchronized (lock3) {
- try {
- lock3.notifyAll();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+ windowFocusGainedLatch.countDown();
}
+ @Override
public void windowLostFocus(WindowEvent event) {
- System.out.println("Frame Focus lost");
+ System.out.println("Frame Focus lost");
}
});
+
frame.addWindowListener(new WindowAdapter() {
+ @Override
public void windowActivated(WindowEvent e) {
- eventType = WindowEvent.WINDOW_ACTIVATED;
- System.out.println("Undecorated Frame is activated\n");
- synchronized (lock1) {
- try {
- lock1.notifyAll();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+ System.out.println("Undecorated Frame is activated");
+ windowActivatedLatch.countDown();
}
+ @Override
public void windowDeactivated(WindowEvent e) {
- eventType = WindowEvent.WINDOW_DEACTIVATED;
- System.out.println("Undecorated Frame got Deactivated\n");
- synchronized (lock2) {
- try {
- lock2.notifyAll();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+ System.out.println("Undecorated Frame got Deactivated");
+ windowDeactivatedLatch.countDown();
}
});
+
textField = new TextField("TextField");
button = new Button("Click me");
- button.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textField.setText("Focus gained");
- }
- });
+ button.addActionListener(e -> textField.setText("Focus gained"));
frame.setBackground(Color.green);
frame.add(button);
@@ -149,86 +126,46 @@ public class ActiveAWTWindowTest {
frame2.setLocation(5, 250);
frame2.setSize(200, 200);
frame2.setBackground(Color.green);
+
button2 = new Button("Click me");
textField2 = new TextField("TextField");
- button2.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textField2.setText("Got the focus");
- }
- });
+ button2.addActionListener(e -> textField2.setText("Got the focus"));
frame2.add(button2, BorderLayout.SOUTH);
frame2.add(textField2, BorderLayout.NORTH);
frame2.setVisible(true);
-
- frame.toFront();
}
- public void doTest() {
- ExtendedRobot robot;
- try {
- robot = new ExtendedRobot();
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException("Cannot create robot");
- }
-
- robot.setAutoDelay(delay);
+ private static void doTest() throws AWTException, InterruptedException {
+ Robot robot = new Robot();
+ robot.setAutoDelay(150);
robot.setAutoWaitForIdle(true);
-
- robot.waitForIdle(5*delay);
- robot.mouseMove(button.getLocationOnScreen().x + button.getSize().width / 2,
- button.getLocationOnScreen().y + button.getSize().height / 2);
- robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
- robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
-
- if (eventType != WindowEvent.WINDOW_ACTIVATED) {
- synchronized (lock1) {
- try {
- lock1.wait(delay * 10);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
+ if (!windowFocusGainedLatch.await(1000, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Frame did not gain focus");
}
- if (eventType != WindowEvent.WINDOW_ACTIVATED) {
- passed = false;
- System.err.println("WINDOW_ACTIVATED event did not occur when the " +
- "undecorated frame is activated!");
+ clickButtonCenter(robot, button);
+
+ if (!windowActivatedLatch.await(1000, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Frame was not activated");
}
+ clickButtonCenter(robot, button2);
- eventType = -1;
-
- robot.mouseMove(button2.getLocationOnScreen().x + button2.getSize().width / 2,
- button2.getLocationOnScreen().y + button2.getSize().height / 2);
- robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
- robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
-
- if (eventType != WindowEvent.WINDOW_DEACTIVATED) {
- synchronized (lock2) {
- try {
- lock2.wait(delay * 10);
- } catch (Exception e) {
- }
- }
- }
- if (eventType != WindowEvent.WINDOW_DEACTIVATED) {
- passed = false;
- System.err.println("FAIL: WINDOW_DEACTIVATED event did not occur for the " +
- "undecorated frame when another frame gains focus!");
+ if (!windowDeactivatedLatch.await(2000, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Frame was not deactivated");
}
if (frame.hasFocus()) {
- passed = false;
- System.err.println("FAIL: The undecorated frame has focus even when " +
- "another frame is clicked!");
- }
-
- if (!passed) {
- //captureScreenAndSave();
- System.err.println("Test failed!");
- throw new RuntimeException("Test failed.");
- } else {
- System.out.println("Test passed");
+ throw new RuntimeException("Frame did not lose focus");
}
}
+
+ private static void clickButtonCenter(Robot robot, Component button) {
+ Point location = button.getLocationOnScreen();
+ Dimension size = button.getSize();
+ int x = location.x + size.width / 2;
+ int y = location.y + size.height / 2;
+ robot.mouseMove(x, y);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ }
}
+
From 4c5e901c96dee3885e1b29a53d3400174f9bba09 Mon Sep 17 00:00:00 2001
From: Francesco Andreuzzi
Date: Thu, 18 Sep 2025 08:25:05 +0000
Subject: [PATCH 029/664] 8367689: Revert removal of several
compilation-related vmStructs fields
Reviewed-by: kevinw, coleenp
---
src/hotspot/share/ci/ciClassList.hpp | 1 +
src/hotspot/share/runtime/vmStructs.cpp | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/src/hotspot/share/ci/ciClassList.hpp b/src/hotspot/share/ci/ciClassList.hpp
index 618a052765e..bce1e52e80b 100644
--- a/src/hotspot/share/ci/ciClassList.hpp
+++ b/src/hotspot/share/ci/ciClassList.hpp
@@ -80,6 +80,7 @@ friend class ciObjectFactory; \
// Any more access must be given explicitly.
#define CI_PACKAGE_ACCESS_TO \
friend class ciObjectFactory; \
+friend class VMStructs; \
friend class ciCallSite; \
friend class ciConstantPoolCache; \
friend class ciField; \
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index bc026887b84..86874a967e3 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -666,6 +666,14 @@
static_field(VMRegImpl, regName[0], const char*) \
static_field(VMRegImpl, stack0, VMReg) \
\
+ /******************************************************************************************/ \
+ /* CI (NOTE: these CI fields are retained in VMStructs for the benefit of external tools, */ \
+ /* to ease their migration to a future alternative.) */ \
+ /******************************************************************************************/ \
+ \
+ nonstatic_field(CompilerThread, _env, ciEnv*) \
+ nonstatic_field(ciEnv, _task, CompileTask*) \
+ \
/************/ \
/* Monitors */ \
/************/ \
@@ -1148,6 +1156,12 @@
declare_toplevel_type(BasicLock) \
declare_toplevel_type(BasicObjectLock) \
\
+ /*********************/ \
+ /* CI */ \
+ /*********************/ \
+ \
+ declare_toplevel_type(ciEnv) \
+ \
/********************/ \
/* -XX flags */ \
/********************/ \
From 04dcaa3412d07c407aed604874095acaf81d7309 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20H=C3=A4ssig?=
Date: Thu, 18 Sep 2025 08:30:05 +0000
Subject: [PATCH 030/664] 8367721: Test
compiler/arguments/TestCompileTaskTimeout.java crashed: SIGSEGV
Reviewed-by: mchevalier, chagedorn
---
src/hotspot/share/compiler/compileBroker.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp
index d1e3154bbd9..24f28821087 100644
--- a/src/hotspot/share/compiler/compileBroker.cpp
+++ b/src/hotspot/share/compiler/compileBroker.cpp
@@ -224,12 +224,15 @@ CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
CompileTaskWrapper::~CompileTaskWrapper() {
CompilerThread* thread = CompilerThread::current();
+
+ // First, disarm the timeout. This still relies on the underlying task.
+ thread->timeout()->disarm();
+
CompileTask* task = thread->task();
CompileLog* log = thread->log();
if (log != nullptr && !task->is_unloaded()) task->log_task_done(log);
thread->set_task(nullptr);
thread->set_env(nullptr);
- thread->timeout()->disarm();
if (task->is_blocking()) {
bool free_task = false;
{
From 4c7c009dd6aa2ce1f65f05c05d7376240f3c01cd Mon Sep 17 00:00:00 2001
From: Francesco Andreuzzi
Date: Thu, 18 Sep 2025 09:09:27 +0000
Subject: [PATCH 031/664] 8367740: assembler_.inline.hpp should not
include assembler.inline.hpp
Reviewed-by: dfenacci, ayang
---
src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp | 2 +-
src/hotspot/cpu/ppc/assembler_ppc.inline.hpp | 2 +-
src/hotspot/cpu/riscv/assembler_riscv.inline.hpp | 2 +-
src/hotspot/cpu/s390/assembler_s390.inline.hpp | 2 +-
src/hotspot/cpu/zero/assembler_zero.inline.hpp | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp
index e7efe472b82..fb14d588f04 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp
@@ -26,7 +26,7 @@
#ifndef CPU_AARCH64_ASSEMBLER_AARCH64_INLINE_HPP
#define CPU_AARCH64_ASSEMBLER_AARCH64_INLINE_HPP
-#include "asm/assembler.inline.hpp"
+#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
index 24601c5d3b0..7e49ec7455d 100644
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
@@ -26,7 +26,7 @@
#ifndef CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
#define CPU_PPC_ASSEMBLER_PPC_INLINE_HPP
-#include "asm/assembler.inline.hpp"
+#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
#include "runtime/vm_version.hpp"
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp
index 1f9e6df2172..e85b64bd6ba 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp
@@ -27,7 +27,7 @@
#ifndef CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP
#define CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP
-#include "asm/assembler.inline.hpp"
+#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
diff --git a/src/hotspot/cpu/s390/assembler_s390.inline.hpp b/src/hotspot/cpu/s390/assembler_s390.inline.hpp
index 567f3d75a62..3bab60f0bb6 100644
--- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp
+++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp
@@ -26,7 +26,7 @@
#ifndef CPU_S390_ASSEMBLER_S390_INLINE_HPP
#define CPU_S390_ASSEMBLER_S390_INLINE_HPP
-#include "asm/assembler.inline.hpp"
+#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
diff --git a/src/hotspot/cpu/zero/assembler_zero.inline.hpp b/src/hotspot/cpu/zero/assembler_zero.inline.hpp
index 0a3f4fc25fa..d78eb39c973 100644
--- a/src/hotspot/cpu/zero/assembler_zero.inline.hpp
+++ b/src/hotspot/cpu/zero/assembler_zero.inline.hpp
@@ -26,7 +26,7 @@
#ifndef CPU_ZERO_ASSEMBLER_ZERO_INLINE_HPP
#define CPU_ZERO_ASSEMBLER_ZERO_INLINE_HPP
-#include "asm/assembler.inline.hpp"
+#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "code/codeCache.hpp"
#include "runtime/handles.inline.hpp"
From a49856bb044057a738ffc4186e1e5e3916c0254c Mon Sep 17 00:00:00 2001
From: Emanuel Peter
Date: Thu, 18 Sep 2025 11:09:40 +0000
Subject: [PATCH 032/664] 8367969: C2:
compiler/vectorapi/TestVectorMathLib.java fails without
UnlockDiagnosticVMOptions
Reviewed-by: shade, mhaessig
---
test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
index 112220262b6..af9e7c051f8 100644
--- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
+++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMathLib.java
@@ -34,7 +34,9 @@ import jdk.incubator.vector.VectorSpecies;
* @modules jdk.incubator.vector
* @library /test/lib
*
- * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:+StressIncrementalInlining -XX:CompileCommand=quiet
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ * -XX:+UnlockDiagnosticVMOptions -XX:+StressIncrementalInlining
+ * -XX:CompileCommand=quiet
* -XX:CompileCommand=compileonly,compiler.vectorapi.TestVectorMathLib::test*
* compiler.vectorapi.TestVectorMathLib
*/
From 5db1dfe5c8b5df40779bb450849e6433aa9825ab Mon Sep 17 00:00:00 2001
From: Christian Stein
Date: Thu, 18 Sep 2025 12:09:47 +0000
Subject: [PATCH 033/664] 8361950: Update to use jtreg 8
Reviewed-by: jpai, iris, joehw, erikj, ihse, liach, alanb
---
make/autoconf/lib-tests.m4 | 2 +-
make/conf/github-actions.conf | 2 +-
make/conf/jib-profiles.js | 6 ++---
test/docs/TEST.ROOT | 2 +-
test/hotspot/jtreg/TEST.ROOT | 2 +-
.../ResourceExhausted/resexhausted003.java | 23 +++++--------------
test/jaxp/TEST.ROOT | 2 +-
test/jdk/TEST.ROOT | 2 +-
.../spi-calendar-provider/TestSPISigned.java | 9 ++++----
test/langtools/TEST.ROOT | 2 +-
test/lib-test/TEST.ROOT | 2 +-
11 files changed, 22 insertions(+), 32 deletions(-)
diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4
index 9eb5ee5a046..23f3d443a6c 100644
--- a/make/autoconf/lib-tests.m4
+++ b/make/autoconf/lib-tests.m4
@@ -28,7 +28,7 @@
################################################################################
# Minimum supported versions
-JTREG_MINIMUM_VERSION=7.5.2
+JTREG_MINIMUM_VERSION=8
GTEST_MINIMUM_VERSION=1.14.0
################################################################################
diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf
index d2b6cd23128..438e4b3ce8d 100644
--- a/make/conf/github-actions.conf
+++ b/make/conf/github-actions.conf
@@ -26,7 +26,7 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
GTEST_VERSION=1.14.0
-JTREG_VERSION=7.5.2+1
+JTREG_VERSION=8+2
LINUX_X64_BOOT_JDK_EXT=tar.gz
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index d4877604a90..7ed72005ced 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "jpg",
product: "jtreg",
- version: "7.5.2",
- build_number: "1",
- file: "bundles/jtreg-7.5.2+1.zip",
+ version: "8",
+ build_number: "2",
+ file: "bundles/jtreg-8+2.zip",
environment_name: "JT_HOME",
environment_path: input.get("jtreg", "home_path") + "/bin",
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
diff --git a/test/docs/TEST.ROOT b/test/docs/TEST.ROOT
index 5ca9b1f144f..bcbfd717dc0 100644
--- a/test/docs/TEST.ROOT
+++ b/test/docs/TEST.ROOT
@@ -38,7 +38,7 @@
groups=TEST.groups
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Use new module options
useNewOptions=true
diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT
index 2d0d972744c..f5b6922e7e1 100644
--- a/test/hotspot/jtreg/TEST.ROOT
+++ b/test/hotspot/jtreg/TEST.ROOT
@@ -104,7 +104,7 @@ requires.properties= \
jdk.static
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../../ notation to reach them
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java
index 8cc997fa4ab..f1d18211f3d 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java
@@ -25,9 +25,10 @@ package nsk.jvmti.ResourceExhausted;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
+import java.net.URI;
+import java.nio.file.Path;
+import java.security.CodeSource;
import java.security.ProtectionDomain;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
import nsk.share.Consts;
import nsk.share.test.Stresser;
@@ -80,24 +81,12 @@ public class resexhausted003 {
public static int run(String args[], PrintStream out) {
- String testclasspath = System.getProperty("test.class.path");
- String [] testpaths = testclasspath.split(System.getProperty("path.separator"));
- String classesDir = "";
-
- Pattern pattern = Pattern.compile("^(.*)classes(.*)vmTestbase(.*)$");
- for (int i = 0 ; i < testpaths.length; i++) {
- if (pattern.matcher(testpaths[i]).matches()) {
- classesDir = testpaths[i];
- }
- }
- if (classesDir.equals("")) {
- System.err.println("TEST BUG: Classes directory not found in test,class.path.");
- return Consts.TEST_FAILED;
- }
Stresser stress = new Stresser(args);
String className = Helper.class.getName();
- byte[] bloatBytes = fileBytes(classesDir + File.separator + className.replace('.', '/') + ".class");
+ CodeSource classCodeSource = Helper.class.getProtectionDomain().getCodeSource();
+ Path classFilePath = Path.of(URI.create(classCodeSource.getLocation().toString()));
+ byte[] bloatBytes = fileBytes(classFilePath.resolve(className.replace('.', '/') + ".class").toString());
int count = 0;
Helper.resetExhaustedEvent();
diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT
index 6398c399f0a..bafa67a700e 100644
--- a/test/jaxp/TEST.ROOT
+++ b/test/jaxp/TEST.ROOT
@@ -23,7 +23,7 @@ modules=java.xml
groups=TEST.groups
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT
index 0fa78bebc3f..9d12d384399 100644
--- a/test/jdk/TEST.ROOT
+++ b/test/jdk/TEST.ROOT
@@ -121,7 +121,7 @@ requires.properties= \
jdk.static
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java
index 83c2d85f6e4..fb54d468d18 100644
--- a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java
+++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Red Hat, Inc.
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +31,7 @@ import java.util.Calendar;
import java.util.Locale;
import java.util.List;
import java.util.ArrayList;
+import java.net.URI;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.Files;
@@ -54,12 +56,9 @@ import static java.util.Calendar.WEDNESDAY;
*/
public class TestSPISigned {
- private static final String TEST_CLASSES = System.getProperty("test.classes", ".");
private static final String TEST_SRC = System.getProperty("test.src", ".");
private static final Path META_INF_DIR = Paths.get(TEST_SRC, "provider", "meta");
- private static final Path PROVIDER_PARENT = Paths.get(TEST_CLASSES, "..");
- private static final Path PROVIDER_DIR = PROVIDER_PARENT.resolve("provider");
private static final Path MODS_DIR = Paths.get("mods");
private static final Path UNSIGNED_JAR = MODS_DIR.resolve("unsigned-with-locale.jar");
private static final Path SIGNED_JAR = MODS_DIR.resolve("signed-with-locale.jar");
@@ -81,7 +80,9 @@ public class TestSPISigned {
// Set up signed jar with custom calendar data provider
//
// 1. Create jar with custom CalendarDataProvider
- JarUtils.createJarFile(UNSIGNED_JAR, PROVIDER_DIR);
+ var codeSource = baz.CalendarDataProviderImpl.class.getProtectionDomain().getCodeSource();
+ var providerDir = Path.of(URI.create(codeSource.getLocation().toString()));
+ JarUtils.createJarFile(UNSIGNED_JAR, providerDir);
JarUtils.updateJarFile(UNSIGNED_JAR, META_INF_DIR);
// create signer's keypair
SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " +
diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT
index e3bd3b74bcf..1aaaa7dffe1 100644
--- a/test/langtools/TEST.ROOT
+++ b/test/langtools/TEST.ROOT
@@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc
groups=TEST.groups
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Use new module options
useNewOptions=true
diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT
index 162e6e15ec2..5710e2e9528 100644
--- a/test/lib-test/TEST.ROOT
+++ b/test/lib-test/TEST.ROOT
@@ -29,7 +29,7 @@
keys=randomness
# Minimum jtreg version
-requiredVersion=7.5.2+1
+requiredVersion=8+2
# Allow querying of various System properties in @requires clauses
requires.extraPropDefns = ../jtreg-ext/requires/VMProps.java
From feaa654b1bb5a1187785320603ccb17e2c43222d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johan=20Sj=C3=B6len?=
Date: Thu, 18 Sep 2025 12:26:50 +0000
Subject: [PATCH 034/664] 8367249: [REDO] MemBaseline accesses VMT without
using lock
Reviewed-by: azafari, cnorrbin
---
src/hotspot/share/nmt/memBaseline.cpp | 72 +++++++------------
src/hotspot/share/nmt/memBaseline.hpp | 13 ++--
src/hotspot/share/nmt/memReporter.cpp | 16 ++---
.../share/nmt/nmtNativeCallStackStorage.cpp | 18 +++++
.../share/nmt/nmtNativeCallStackStorage.hpp | 3 +-
src/hotspot/share/nmt/regionsTree.cpp | 13 +++-
src/hotspot/share/nmt/regionsTree.hpp | 10 ++-
src/hotspot/share/nmt/vmatree.cpp | 7 ++
src/hotspot/share/nmt/vmatree.hpp | 12 +++-
src/hotspot/share/utilities/rbTree.hpp | 12 ++--
src/hotspot/share/utilities/rbTree.inline.hpp | 49 +++++++++++++
test/hotspot/gtest/utilities/test_rbtree.cpp | 40 +++++++++++
12 files changed, 189 insertions(+), 76 deletions(-)
diff --git a/src/hotspot/share/nmt/memBaseline.cpp b/src/hotspot/share/nmt/memBaseline.cpp
index d94aa10eab1..118e3ec64c0 100644
--- a/src/hotspot/share/nmt/memBaseline.cpp
+++ b/src/hotspot/share/nmt/memBaseline.cpp
@@ -27,8 +27,7 @@
#include "memory/metaspaceUtils.hpp"
#include "nmt/memBaseline.hpp"
#include "nmt/memTracker.hpp"
-#include "runtime/javaThread.hpp"
-#include "runtime/safepoint.hpp"
+#include "nmt/regionsTree.inline.hpp"
/*
* Sizes are sorted in descenting order for reporting
@@ -104,38 +103,6 @@ class MallocAllocationSiteWalker : public MallocSiteWalker {
}
};
-// Walk all virtual memory regions for baselining
-class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
- private:
- typedef LinkedListImpl EntryList;
- EntryList _virtual_memory_regions;
- DEBUG_ONLY(address _last_base;)
- public:
- VirtualMemoryAllocationWalker() {
- DEBUG_ONLY(_last_base = nullptr);
- }
-
- bool do_allocation_site(const ReservedMemoryRegion* rgn) {
- assert(rgn->base() >= _last_base, "region unordered?");
- DEBUG_ONLY(_last_base = rgn->base());
- if (rgn->size() > 0) {
- if (_virtual_memory_regions.add(*rgn) != nullptr) {
- return true;
- } else {
- return false;
- }
- } else {
- // Ignore empty sites.
- return true;
- }
- }
-
- LinkedList* virtual_memory_allocations() {
- return &_virtual_memory_regions;
- }
-};
-
void MemBaseline::baseline_summary() {
MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
{
@@ -158,14 +125,15 @@ bool MemBaseline::baseline_allocation_sites() {
// The malloc sites are collected in size order
_malloc_sites_order = by_size;
- // Virtual memory allocation sites
- VirtualMemoryAllocationWalker virtual_memory_walker;
- if (!MemTracker::walk_virtual_memory(&virtual_memory_walker)) {
- return false;
- }
+ assert(_vma_allocations == nullptr, "must");
- // Virtual memory allocations are collected in call stack order
- _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
+ {
+ MemTracker::NmtVirtualMemoryLocker locker;
+ _vma_allocations = new (mtNMT, std::nothrow) RegionsTree(*VirtualMemoryTracker::Instance::tree());
+ if (_vma_allocations == nullptr) {
+ return false;
+ }
+ }
if (!aggregate_virtual_memory_allocation_sites()) {
return false;
@@ -202,20 +170,28 @@ int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
SortedLinkedList allocation_sites;
- VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
- const ReservedMemoryRegion* rgn;
VirtualMemoryAllocationSite* site;
- while ((rgn = itr.next()) != nullptr) {
- VirtualMemoryAllocationSite tmp(*rgn->call_stack(), rgn->mem_tag());
+ bool failed_oom = false;
+ _vma_allocations->visit_reserved_regions([&](ReservedMemoryRegion& rgn) {
+ VirtualMemoryAllocationSite tmp(*rgn.call_stack(), rgn.mem_tag());
site = allocation_sites.find(tmp);
if (site == nullptr) {
LinkedListNode* node =
allocation_sites.add(tmp);
- if (node == nullptr) return false;
+ if (node == nullptr) {
+ failed_oom = true;
+ return false;
+ }
site = node->data();
}
- site->reserve_memory(rgn->size());
- site->commit_memory(VirtualMemoryTracker::Instance::committed_size(rgn));
+ site->reserve_memory(rgn.size());
+
+ site->commit_memory(_vma_allocations->committed_size(rgn));
+ return true;
+ });
+
+ if (failed_oom) {
+ return false;
}
_virtual_memory_sites.move(&allocation_sites);
diff --git a/src/hotspot/share/nmt/memBaseline.hpp b/src/hotspot/share/nmt/memBaseline.hpp
index 2fff4cc666c..3f1ea46d815 100644
--- a/src/hotspot/share/nmt/memBaseline.hpp
+++ b/src/hotspot/share/nmt/memBaseline.hpp
@@ -35,7 +35,6 @@
typedef LinkedListIterator MallocSiteIterator;
typedef LinkedListIterator VirtualMemorySiteIterator;
-typedef LinkedListIterator VirtualMemoryAllocationIterator;
/*
* Baseline a memory snapshot
@@ -71,7 +70,7 @@ class MemBaseline {
LinkedListImpl _malloc_sites;
// All virtual memory allocations
- LinkedListImpl _virtual_memory_allocations;
+ RegionsTree* _vma_allocations;
// Virtual memory allocations by allocation sites, always in by_address
// order
@@ -86,6 +85,7 @@ class MemBaseline {
// create a memory baseline
MemBaseline():
_instance_class_count(0), _array_class_count(0), _thread_count(0),
+ _vma_allocations(nullptr),
_baseline_type(Not_baselined) {
}
@@ -110,9 +110,9 @@ class MemBaseline {
// Virtual memory allocation iterator always returns in virtual memory
// base address order.
- VirtualMemoryAllocationIterator virtual_memory_allocations() {
- assert(!_virtual_memory_allocations.is_empty(), "Not detail baseline");
- return VirtualMemoryAllocationIterator(_virtual_memory_allocations.head());
+ RegionsTree* virtual_memory_allocations() {
+ assert(_vma_allocations != nullptr, "Not detail baseline");
+ return _vma_allocations;
}
// Total reserved memory = total malloc'd memory + total reserved virtual
@@ -185,7 +185,8 @@ class MemBaseline {
_malloc_sites.clear();
_virtual_memory_sites.clear();
- _virtual_memory_allocations.clear();
+ delete _vma_allocations;
+ _vma_allocations = nullptr;
}
private:
diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp
index 65d4d76942b..772bda2885b 100644
--- a/src/hotspot/share/nmt/memReporter.cpp
+++ b/src/hotspot/share/nmt/memReporter.cpp
@@ -394,13 +394,11 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() {
void MemDetailReporter::report_virtual_memory_map() {
// Virtual memory map always in base address order
- VirtualMemoryAllocationIterator itr = _baseline.virtual_memory_allocations();
- const ReservedMemoryRegion* rgn;
-
output()->print_cr("Virtual memory map:");
- while ((rgn = itr.next()) != nullptr) {
- report_virtual_memory_region(rgn);
- }
+ _baseline.virtual_memory_allocations()->visit_reserved_regions([&](ReservedMemoryRegion& rgn) {
+ report_virtual_memory_region(&rgn);
+ return true;
+ });
}
void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) {
@@ -421,7 +419,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
outputStream* out = output();
const char* scale = current_scale();
const NativeCallStack* stack = reserved_rgn->call_stack();
- bool all_committed = reserved_rgn->size() == VirtualMemoryTracker::Instance::committed_size(reserved_rgn);
+ bool all_committed = reserved_rgn->size() == _baseline.virtual_memory_allocations()->committed_size(*reserved_rgn);
const char* region_type = (all_committed ? "reserved and committed" : "reserved");
out->cr();
print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size());
@@ -435,7 +433,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
if (all_committed) {
bool reserved_and_committed = false;
- VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*reserved_rgn,
+ _baseline.virtual_memory_allocations()->visit_committed_regions(*reserved_rgn,
[&](CommittedMemoryRegion& committed_rgn) {
if (committed_rgn.equals(*reserved_rgn)) {
// One region spanning the entire reserved region, with the same stack trace.
@@ -468,7 +466,7 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion*
)
};
- VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*reserved_rgn,
+ _baseline.virtual_memory_allocations()->visit_committed_regions(*reserved_rgn,
[&](CommittedMemoryRegion& crgn) {
print_committed_rgn(crgn);
return true;
diff --git a/src/hotspot/share/nmt/nmtNativeCallStackStorage.cpp b/src/hotspot/share/nmt/nmtNativeCallStackStorage.cpp
index 3e5c1d2f0ea..9a2ecd57ecc 100644
--- a/src/hotspot/share/nmt/nmtNativeCallStackStorage.cpp
+++ b/src/hotspot/share/nmt/nmtNativeCallStackStorage.cpp
@@ -57,3 +57,21 @@ NativeCallStackStorage::NativeCallStackStorage(bool is_detailed_mode, int table_
NativeCallStackStorage::~NativeCallStackStorage() {
FREE_C_HEAP_ARRAY(LinkPtr, _table);
}
+
+NativeCallStackStorage::NativeCallStackStorage(const NativeCallStackStorage& other)
+ : _table_size(other._table_size),
+ _table(nullptr),
+ _stacks(),
+ _is_detailed_mode(other._is_detailed_mode),
+ _fake_stack(other._fake_stack) {
+ if (_is_detailed_mode) {
+ _table = NEW_C_HEAP_ARRAY(TableEntryIndex, _table_size, mtNMT);
+ for (int i = 0; i < _table_size; i++) {
+ _table[i] = other._table[i];
+ }
+ }
+ _stacks.reserve(other._stacks.length());
+ for (int i = 0; i < other._stacks.length(); i++) {
+ _stacks.at_grow(i) = other._stacks.at(i);
+ }
+}
diff --git a/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp b/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp
index 6f194cfa5a1..6ead8f49248 100644
--- a/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp
+++ b/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp
@@ -95,7 +95,8 @@ public:
}
NativeCallStackStorage(bool is_detailed_mode, int table_size = default_table_size);
-
+ NativeCallStackStorage(const NativeCallStackStorage& other);
+ NativeCallStackStorage& operator=(const NativeCallStackStorage& other) = delete;
~NativeCallStackStorage();
};
diff --git a/src/hotspot/share/nmt/regionsTree.cpp b/src/hotspot/share/nmt/regionsTree.cpp
index 370c69a2485..a2f5a5df67a 100644
--- a/src/hotspot/share/nmt/regionsTree.cpp
+++ b/src/hotspot/share/nmt/regionsTree.cpp
@@ -22,6 +22,8 @@
*
*/
#include "nmt/regionsTree.hpp"
+#include "nmt/regionsTree.inline.hpp"
+#include "nmt/virtualMemoryTracker.hpp"
VMATree::SummaryDiff RegionsTree::commit_region(address addr, size_t size, const NativeCallStack& stack) {
return commit_mapping((VMATree::position)addr, size, make_region_data(stack, mtNone), /*use tag inplace*/ true);
@@ -54,4 +56,13 @@ void RegionsTree::print_on(outputStream* st) {
return true;
});
}
-#endif
\ No newline at end of file
+#endif
+
+size_t RegionsTree::committed_size(const ReservedMemoryRegion& rgn) {
+ size_t result = 0;
+ visit_committed_regions(rgn, [&](CommittedMemoryRegion& crgn) {
+ result += crgn.size();
+ return true;
+ });
+ return result;
+}
diff --git a/src/hotspot/share/nmt/regionsTree.hpp b/src/hotspot/share/nmt/regionsTree.hpp
index bf2ab711b2d..35272c27423 100644
--- a/src/hotspot/share/nmt/regionsTree.hpp
+++ b/src/hotspot/share/nmt/regionsTree.hpp
@@ -40,6 +40,12 @@ class RegionsTree : public VMATree {
public:
RegionsTree(bool with_storage) : VMATree() , _ncs_storage(with_storage), _with_storage(with_storage) { }
+ RegionsTree(const RegionsTree& other)
+ : VMATree(other),
+ _ncs_storage(other._ncs_storage),
+ _with_storage(other._with_storage) {}
+ RegionsTree& operator=(const RegionsTree& other) = delete;
+
ReservedMemoryRegion find_reserved_region(address addr);
SummaryDiff commit_region(address addr, size_t size, const NativeCallStack& stack);
@@ -91,6 +97,8 @@ class RegionsTree : public VMATree {
NativeCallStackStorage::StackIndex si = node.out_stack_index();
return _ncs_storage.get(si);
}
+
+ size_t committed_size(const ReservedMemoryRegion& rgn);
};
-#endif // NMT_REGIONSTREE_HPP
\ No newline at end of file
+#endif // NMT_REGIONSTREE_HPP
diff --git a/src/hotspot/share/nmt/vmatree.cpp b/src/hotspot/share/nmt/vmatree.cpp
index 4f6f8e12185..69887068cb2 100644
--- a/src/hotspot/share/nmt/vmatree.cpp
+++ b/src/hotspot/share/nmt/vmatree.cpp
@@ -744,3 +744,10 @@ void VMATree::SummaryDiff::print_on(outputStream* out) {
}
}
#endif
+
+void VMATree::clear() {
+ _tree.remove_all();
+};
+bool VMATree::is_empty() {
+ return _tree.size() == 0;
+};
diff --git a/src/hotspot/share/nmt/vmatree.hpp b/src/hotspot/share/nmt/vmatree.hpp
index 1b5729054e4..dff2491c69c 100644
--- a/src/hotspot/share/nmt/vmatree.hpp
+++ b/src/hotspot/share/nmt/vmatree.hpp
@@ -30,6 +30,7 @@
#include "nmt/nmtNativeCallStackStorage.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
+#include "utilities/rbTree.hpp"
#include "utilities/rbTree.inline.hpp"
#include
@@ -39,7 +40,7 @@
// For example, the state may go from released memory to committed memory,
// or from committed memory of a certain MemTag to committed memory of a different MemTag.
// The set of points is stored in a balanced binary tree for efficient querying and updating.
-class VMATree {
+class VMATree : public CHeapObjBase {
friend class NMTVMATreeTest;
friend class VMTWithVMATreeTest;
// A position in memory.
@@ -65,7 +66,6 @@ private:
static const char* statetype_strings[static_cast(StateType::st_number_of_states)];
public:
- NONCOPYABLE(VMATree);
static const char* statetype_to_string(StateType type) {
assert(type < StateType::st_number_of_states, "must be");
@@ -226,6 +226,11 @@ private:
public:
VMATree() : _tree() {}
+ VMATree(const VMATree& other) : _tree() {
+ bool success = other._tree.copy_into(_tree);
+ assert(success, "VMATree dies on OOM");
+ }
+ VMATree& operator=(VMATree const&) = delete;
struct SingleDiff {
using delta = int64_t;
@@ -329,5 +334,8 @@ public:
_tree.visit_range_in_order(from, to, f);
}
VMARBTree& tree() { return _tree; }
+
+ void clear();
+ bool is_empty();
};
#endif
diff --git a/src/hotspot/share/utilities/rbTree.hpp b/src/hotspot/share/utilities/rbTree.hpp
index 4c358b53ff0..2c4edcc2070 100644
--- a/src/hotspot/share/utilities/rbTree.hpp
+++ b/src/hotspot/share/utilities/rbTree.hpp
@@ -428,6 +428,7 @@ public:
template
void visit_in_order(F f);
+
// Visit all RBNodes in ascending order whose keys are in range [from, to], calling f on each node.
// If f returns `true` the iteration continues, otherwise it is stopped at the current node.
template
@@ -475,15 +476,10 @@ class RBTree : public AbstractRBTree, COMPARATOR> {
public:
RBTree() : BaseType(), _allocator() {}
+ NONCOPYABLE(RBTree);
~RBTree() { remove_all(); }
- RBTree(const RBTree& other) : BaseType(), _allocator() {
- assert(std::is_copy_constructible(), "Value type must be copy-constructible");
- other.visit_in_order([&](auto node) {
- this->upsert(node->key(), node->val());
- return true;
- });
- }
- RBTree& operator=(const RBTree& other) = delete;
+
+ bool copy_into(RBTree& other) const;
typedef typename BaseType::Cursor Cursor;
using BaseType::cursor;
diff --git a/src/hotspot/share/utilities/rbTree.inline.hpp b/src/hotspot/share/utilities/rbTree.inline.hpp
index f28923eb867..b7de0a7ac4c 100644
--- a/src/hotspot/share/utilities/rbTree.inline.hpp
+++ b/src/hotspot/share/utilities/rbTree.inline.hpp
@@ -753,4 +753,53 @@ void AbstractRBTree::print_on(outputStream* st, const P
}
}
+template
+bool RBTree::copy_into(RBTree& other) const {
+ assert(other.size() == 0, "You can only copy into an empty RBTree");
+ assert(std::is_copy_constructible::value, "Key type must be copy-constructible when copying a RBTree");
+ assert(std::is_copy_constructible::value, "Value type must be copy-constructible when copying a RBTree");
+ enum class Dir { Left, Right };
+ struct node_pair { const IntrusiveRBNode* current; IntrusiveRBNode* other_parent; Dir dir; };
+ struct stack {
+ node_pair s[64];
+ int idx = 0;
+ stack() : idx(0) {}
+ node_pair pop() { idx--; return s[idx]; };
+ void push(node_pair n) { s[idx] = n; idx++; };
+ bool is_empty() { return idx == 0; };
+ };
+
+ stack visit_stack;
+ if (this->_root == nullptr) {
+ return true;
+ }
+ RBNode* root = static_cast*>(this->_root);
+ other._root = other.allocate_node(root->key(), root->val());
+ if (other._root == nullptr) return false;
+
+ visit_stack.push({this->_root->_left, other._root, Dir::Left});
+ visit_stack.push({this->_root->_right, other._root, Dir::Right});
+ while (!visit_stack.is_empty()) {
+ node_pair n = visit_stack.pop();
+ const RBNode* current = static_cast*>(n.current);
+ if (current == nullptr) continue;
+ RBNode* new_node = other.allocate_node(current->key(), current->val());
+ if (new_node == nullptr) {
+ return false;
+ }
+ if (n.dir == Dir::Left) {
+ n.other_parent->_left = new_node;
+ } else {
+ n.other_parent->_right = new_node;
+ }
+ new_node->set_parent(n.other_parent);
+ new_node->_parent |= n.current->_parent & 0x1;
+ visit_stack.push({n.current->_left, new_node, Dir::Left});
+ visit_stack.push({n.current->_right, new_node, Dir::Right});
+ }
+ other._num_nodes = this->_num_nodes;
+ DEBUG_ONLY(other._expected_visited = this->_expected_visited);
+ return true;
+}
+
#endif // SHARE_UTILITIES_RBTREE_INLINE_HPP
diff --git a/test/hotspot/gtest/utilities/test_rbtree.cpp b/test/hotspot/gtest/utilities/test_rbtree.cpp
index ff234dd764a..a351e2141e8 100644
--- a/test/hotspot/gtest/utilities/test_rbtree.cpp
+++ b/test/hotspot/gtest/utilities/test_rbtree.cpp
@@ -1200,6 +1200,46 @@ TEST_VM_F(RBTreeTest, VerifyItThroughStressTest) {
}
}
+TEST_VM_F(RBTreeTest, TestCopyInto) {
+ {
+ RBTreeInt rbtree1;
+ RBTreeInt rbtree2;
+
+ rbtree1.copy_into(rbtree2);
+ rbtree2.verify_self();
+ }
+
+ RBTreeInt rbtree1;
+ RBTreeInt rbtree2;
+
+ int size = 1000;
+ for (int i = 0; i < size; i++) {
+ rbtree1.upsert(i, i);
+ }
+
+ rbtree1.copy_into(rbtree2);
+ rbtree2.verify_self();
+
+ ResourceMark rm;
+ GrowableArray allocations(size);
+ int size1 = 0;
+ rbtree1.visit_in_order([&](RBTreeIntNode* node) {
+ size1++;
+ allocations.append(node->key());
+ return true;
+ });
+
+ int size2 = 0;
+ rbtree2.visit_in_order([&](RBTreeIntNode* node) {
+ EXPECT_EQ(node->key(), allocations.at(size2++));
+ return true;
+ });
+
+ EXPECT_EQ(size1, size2);
+ EXPECT_EQ(rbtree1.size(), rbtree2.size());
+ EXPECT_EQ(size2, static_cast(rbtree2.size()));
+}
+
struct OomAllocator {
void* allocate(size_t sz) {
return nullptr;
From c927291ecfa3a3871a1eed006687a3e9db4f6811 Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Thu, 18 Sep 2025 15:08:37 +0000
Subject: [PATCH 035/664] 8367739: Serial: Retry allocation after lock acquire
in mem_allocate_work
Reviewed-by: fandreuzzi, tschatzl
---
src/hotspot/share/gc/serial/serialHeap.cpp | 39 ++++++++++++++++------
src/hotspot/share/gc/serial/serialHeap.hpp | 1 +
2 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp
index e019144d628..f26e4427062 100644
--- a/src/hotspot/share/gc/serial/serialHeap.cpp
+++ b/src/hotspot/share/gc/serial/serialHeap.cpp
@@ -292,27 +292,44 @@ HeapWord* SerialHeap::expand_heap_and_allocate(size_t size, bool is_tlab) {
return result;
}
+HeapWord* SerialHeap::mem_allocate_cas_noexpand(size_t size, bool is_tlab) {
+ HeapWord* result = _young_gen->par_allocate(size);
+ if (result != nullptr) {
+ return result;
+ }
+ // Try old-gen allocation for non-TLAB.
+ if (!is_tlab) {
+ // If it's too large for young-gen or heap is too full.
+ if (size > heap_word_size(_young_gen->capacity_before_gc()) || _is_heap_almost_full) {
+ result = _old_gen->par_allocate(size);
+ if (result != nullptr) {
+ return result;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
HeapWord* SerialHeap::mem_allocate_work(size_t size, bool is_tlab) {
HeapWord* result = nullptr;
for (uint try_count = 1; /* break */; try_count++) {
- result = _young_gen->par_allocate(size);
+ result = mem_allocate_cas_noexpand(size, is_tlab);
if (result != nullptr) {
break;
}
- // Try old-gen allocation for non-TLAB.
- if (!is_tlab) {
- // If it's too large for young-gen or heap is too full.
- if (size > heap_word_size(_young_gen->capacity_before_gc()) || _is_heap_almost_full) {
- result = _old_gen->par_allocate(size);
- if (result != nullptr) {
- break;
- }
- }
- }
uint gc_count_before; // Read inside the Heap_lock locked region.
{
MutexLocker ml(Heap_lock);
+
+ // Re-try after acquiring the lock, because a GC might have occurred
+ // while waiting for this lock.
+ result = mem_allocate_cas_noexpand(size, is_tlab);
+ if (result != nullptr) {
+ break;
+ }
+
gc_count_before = total_collections();
}
diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp
index 86fb286f33f..388da13b1b0 100644
--- a/src/hotspot/share/gc/serial/serialHeap.hpp
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp
@@ -222,6 +222,7 @@ private:
// Try to allocate space by expanding the heap.
HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab);
+ HeapWord* mem_allocate_cas_noexpand(size_t size, bool is_tlab);
HeapWord* mem_allocate_work(size_t size, bool is_tlab);
MemoryPool* _eden_pool;
From 72e5ad3d21effff6a4efae8ab3ed45c4f6bfba76 Mon Sep 17 00:00:00 2001
From: Ben Perez
Date: Thu, 18 Sep 2025 15:23:05 +0000
Subject: [PATCH 036/664] 8365581: Optimize Java implementation of P256
arithmetic
Reviewed-by: jnimeh
---
.../MontgomeryIntegerPolynomialP256.java | 24 ++++---------------
1 file changed, 5 insertions(+), 19 deletions(-)
diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java b/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java
index 1910746fe44..987b6967b50 100644
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java
+++ b/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java
@@ -32,6 +32,7 @@ import sun.security.util.math.IntegerFieldModuloP;
import java.math.BigInteger;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.vm.annotation.Stable;
// Reference:
// - [1] Shay Gueron and Vlad Krasnov "Fast Prime Field Elliptic Curve
@@ -63,7 +64,7 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
private static final long[] zero = new long[] {
0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L,
0x0000000000000000L, 0x0000000000000000L };
- private static final long[] modulus = new long[] {
+ @Stable private static final long[] modulus = new long[] {
0x000fffffffffffffL, 0x00000fffffffffffL, 0x0000000000000000L,
0x0000001000000000L, 0x0000ffffffff0000L };
@@ -207,9 +208,8 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
n1 = n * modulus[1];
nn1 = Math.unsignedMultiplyHigh(n, modulus[1]) << shift1 | (n1 >>> shift2);
n1 &= LIMB_MASK;
- n2 = n * modulus[2];
- nn2 = Math.unsignedMultiplyHigh(n, modulus[2]) << shift1 | (n2 >>> shift2);
- n2 &= LIMB_MASK;
+ n2 = 0;
+ nn2 = 0;
n3 = n * modulus[3];
nn3 = Math.unsignedMultiplyHigh(n, modulus[3]) << shift1 | (n3 >>> shift2);
n3 &= LIMB_MASK;
@@ -221,8 +221,6 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
d0 += n0;
dd1 += nn1;
d1 += n1;
- dd2 += nn2;
- d2 += n2;
dd3 += nn3;
d3 += n3;
dd4 += nn4;
@@ -259,9 +257,6 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
n1 = n * modulus[1];
dd1 += Math.unsignedMultiplyHigh(n, modulus[1]) << shift1 | (n1 >>> shift2);
d1 += n1 & LIMB_MASK;
- n2 = n * modulus[2];
- dd2 += Math.unsignedMultiplyHigh(n, modulus[2]) << shift1 | (n2 >>> shift2);
- d2 += n2 & LIMB_MASK;
n3 = n * modulus[3];
dd3 += Math.unsignedMultiplyHigh(n, modulus[3]) << shift1 | (n3 >>> shift2);
d3 += n3 & LIMB_MASK;
@@ -300,9 +295,6 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
n1 = n * modulus[1];
dd1 += Math.unsignedMultiplyHigh(n, modulus[1]) << shift1 | (n1 >>> shift2);
d1 += n1 & LIMB_MASK;
- n2 = n * modulus[2];
- dd2 += Math.unsignedMultiplyHigh(n, modulus[2]) << shift1 | (n2 >>> shift2);
- d2 += n2 & LIMB_MASK;
n3 = n * modulus[3];
dd3 += Math.unsignedMultiplyHigh(n, modulus[3]) << shift1 | (n3 >>> shift2);
d3 += n3 & LIMB_MASK;
@@ -341,9 +333,6 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
n1 = n * modulus[1];
dd1 += Math.unsignedMultiplyHigh(n, modulus[1]) << shift1 | (n1 >>> shift2);
d1 += n1 & LIMB_MASK;
- n2 = n * modulus[2];
- dd2 += Math.unsignedMultiplyHigh(n, modulus[2]) << shift1 | (n2 >>> shift2);
- d2 += n2 & LIMB_MASK;
n3 = n * modulus[3];
dd3 += Math.unsignedMultiplyHigh(n, modulus[3]) << shift1 | (n3 >>> shift2);
d3 += n3 & LIMB_MASK;
@@ -382,9 +371,6 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
n1 = n * modulus[1];
dd1 += Math.unsignedMultiplyHigh(n, modulus[1]) << shift1 | (n1 >>> shift2);
d1 += n1 & LIMB_MASK;
- n2 = n * modulus[2];
- dd2 += Math.unsignedMultiplyHigh(n, modulus[2]) << shift1 | (n2 >>> shift2);
- d2 += n2 & LIMB_MASK;
n3 = n * modulus[3];
dd3 += Math.unsignedMultiplyHigh(n, modulus[3]) << shift1 | (n3 >>> shift2);
d3 += n3 & LIMB_MASK;
@@ -411,7 +397,7 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial
c0 = c5 - modulus[0];
c1 = c6 - modulus[1] + (c0 >> BITS_PER_LIMB);
c0 &= LIMB_MASK;
- c2 = c7 - modulus[2] + (c1 >> BITS_PER_LIMB);
+ c2 = c7 + (c1 >> BITS_PER_LIMB);
c1 &= LIMB_MASK;
c3 = c8 - modulus[3] + (c2 >> BITS_PER_LIMB);
c2 &= LIMB_MASK;
From b8f2c7387f4b5a60a6b671619d968d1d77aa9c27 Mon Sep 17 00:00:00 2001
From: Chris Plummer
Date: Thu, 18 Sep 2025 15:35:32 +0000
Subject: [PATCH 037/664] 8367614: Test
vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java failed,
passed and timed-out
Reviewed-by: dholmes, sspitsyn
---
.../referringObjects001.java | 1 +
.../referringObjects003.java | 67 ++++++-------------
2 files changed, 23 insertions(+), 45 deletions(-)
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java
index b5ea8c34cbd..8cc023acaae 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java
@@ -244,6 +244,7 @@ public class referringObjects001 extends HeapwalkingDebugger {
}
}
} catch (Throwable t) {
+ setSuccess(false);
log.complain("Unexpected exception:");
t.printStackTrace(log.getOutStream());
}
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java
index 862600dc697..a04b323d0d1 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2025, 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
@@ -45,12 +45,11 @@
* - Debugee VM
* - stop all threads and remove all references to threads and thread group
* - Debugger VM
- * - check that thread group have only 1 referrer: parent thread group
- * - check that threre are no references to test threads in target VM
- * - Debugger VM
- * - test ObjectReference.disableCollection, ObjectReference.enableCollection for ThreadGroupReference:
- * can't force collection of thread group because of thread group always has 1 referrer - parent thread group, so
- * just test disableCollection/enableCollection don't throw any unexpected exceptions
+ * - force GC
+ * - check that the test thread group has been collected. The reference from the
+ * parent thread group is weak and should not prevent the test thread group from
+ * being collected.
+ * - check that there are no references to test threads in target VM
*
* @requires !vm.graal.enabled
* @library /vmTestbase
@@ -107,9 +106,8 @@ public class referringObjects003 extends HeapwalkingDebugger {
if (referrerCount != expectedCount) {
setSuccess(false);
- log
- .complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadGroupReference): "
- + referrerCount + ", expected: " + expectedCount);
+ log.complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadGroupReference): "
+ + referrerCount + ", expected: " + expectedCount);
}
}
}
@@ -181,57 +179,36 @@ public class referringObjects003 extends HeapwalkingDebugger {
if (!isDebuggeeReady())
return;
- checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size() + 1);
+ // Force the test ThreadGroup to be collected. The only reference to it is a weak
+ // reference from the parent ThreadGroup.
+ forceGC();
+
+ checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size());
checkDebugeeAnswer_instances("java.lang.Thread", threadsToFilter.size());
threadGroups = HeapwalkingDebugger.filterObjectReferrence(threadGroupsToFilter, HeapwalkingDebugger
.getObjectReferences("java.lang.ThreadGroup", vm));
- // 1 referrer(parent thread group) is left
- checkThreadGroupReferrersCount(threadGroups, 1);
+ if (threadGroups.size() != 0) {
+ setSuccess(false);
+ log.complain("All test threads groups should be removed");
+ log.complain("Unexpected threads groups:");
+ for (ObjectReference objectReference : threadGroups) {
+ log.complain(objectReference.toString());
+ }
+ }
threads = HeapwalkingDebugger.filterObjectReferrence(threadsToFilter, HeapwalkingDebugger.getObjectReferences(
"java.lang.Thread",
vm));
if (threads.size() != 0) {
+ setSuccess(false);
log.complain("All test threads should be removed");
log.complain("Unexpected threads:");
for (ObjectReference objectReference : threads) {
log.complain(objectReference.toString());
}
}
-
- checkThreadGroupDisableCollection(threadGroups);
- }
-
- // can't force collection of thread group because of 1 reference is always
- // left in parent tread group
- public void checkThreadGroupDisableCollection(List objectReferences) {
- try {
- for (ObjectReference objectReference : objectReferences)
- objectReference.disableCollection();
- } catch (Throwable t) {
- log.complain("Unexpected exception: " + t);
- t.printStackTrace(log.getOutStream());
- }
-
- forceGC();
- try {
- for (ObjectReference objectReference : objectReferences)
- objectReference.enableCollection();
- } catch (Throwable t) {
- log.complain("Unexpected exception: " + t);
- t.printStackTrace(log.getOutStream());
- }
-
- forceGC();
- try {
- for (ObjectReference objectReference : objectReferences)
- objectReference.referringObjects(0);
- } catch (Throwable t) {
- log.complain("Unexpected exception: " + t);
- t.printStackTrace(log.getOutStream());
- }
}
}
From c597384ad64c7107fba4e970aa435a141276b2fd Mon Sep 17 00:00:00 2001
From: Kelvin Nilsen
Date: Thu, 18 Sep 2025 16:06:59 +0000
Subject: [PATCH 038/664] 8367708: GenShen: Reduce total evacuation burden
Reviewed-by: wkemper
---
.../heuristics/shenandoahOldHeuristics.cpp | 2 +-
.../share/gc/shenandoah/shenandoahGeneration.cpp | 10 +++++-----
.../shenandoahGenerationalEvacuationTask.cpp | 8 +++++++-
.../share/gc/shenandoah/shenandoah_globals.hpp | 16 +++++++++++++++-
4 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
index 2d0bbfd5e4a..2361a50e76d 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
@@ -412,7 +412,7 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() {
size_t defrag_count = 0;
size_t total_uncollected_old_regions = _last_old_region - _last_old_collection_candidate;
- if (cand_idx > _last_old_collection_candidate) {
+ if ((ShenandoahGenerationalHumongousReserve > 0) && (cand_idx > _last_old_collection_candidate)) {
// Above, we have added into the set of mixed-evacuation candidates all old-gen regions for which the live memory
// that they contain is below a particular old-garbage threshold. Regions that were not selected for the collection
// set hold enough live memory that it is not considered efficient (by "garbage-first standards") to compact these
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
index 25afcfcb10e..fafa3fde437 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
@@ -535,6 +535,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100;
+ const size_t pip_used_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage) / 100;
+
size_t old_consumed = 0;
size_t promo_potential = 0;
size_t candidates = 0;
@@ -557,10 +559,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
continue;
}
if (heap->is_tenurable(r)) {
- if ((r->garbage() < old_garbage_threshold)) {
- // This tenure-worthy region has too little garbage, so we do not want to expend the copying effort to
- // reclaim the garbage; instead this region may be eligible for promotion-in-place to the
- // old generation.
+ if ((r->garbage() < old_garbage_threshold) && (r->used() > pip_used_threshold)) {
+ // We prefer to promote this region in place because is has a small amount of garbage and a large usage.
HeapWord* tams = ctx->top_at_mark_start(r);
HeapWord* original_top = r->top();
if (!heap->is_concurrent_old_mark_in_progress() && tams == original_top) {
@@ -586,7 +586,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
// Else, we do not promote this region (either in place or by copy) because it has received new allocations.
// During evacuation, we exclude from promotion regions for which age > tenure threshold, garbage < garbage-threshold,
- // and get_top_before_promote() != tams
+ // used > pip_used_threshold, and get_top_before_promote() != tams
} else {
// Record this promotion-eligible candidate region. After sorting and selecting the best candidates below,
// we may still decide to exclude this promotion-eligible region from the current collection set. If this
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
index 3a0d7926865..971129beea8 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
@@ -146,7 +146,13 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe
// more garbage than ShenandoahOldGarbageThreshold, we'll promote by evacuation. If there is room for evacuation
// in this cycle, the region will be in the collection set. If there is not room, the region will be promoted
// by evacuation in some future GC cycle.
- promote_humongous(r);
+
+ // We do not promote primitive arrays because there's no performance penalty keeping them in young. When/if they
+ // become garbage, reclaiming the memory from young is much quicker and more efficient than reclaiming them from old.
+ oop obj = cast_to_oop(r->bottom());
+ if (!obj->is_typeArray()) {
+ promote_humongous(r);
+ }
} else if (r->is_regular() && (r->get_top_before_promote() != nullptr)) {
// Likewise, we cannot put promote-in-place regions into the collection set because that would also trigger
// the LRB to copy on reference fetch.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
index 1321baa6366..c6a842c7754 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
@@ -34,6 +34,20 @@
range, \
constraint) \
\
+ product(uintx, ShenandoahGenerationalMinPIPUsage, 30, EXPERIMENTAL, \
+ "(Generational mode only) What percent of a heap region " \
+ "should be used before we consider promoting a region in " \
+ "place? Regions with less than this amount of used will " \
+ "promoted by evacuation. A benefit of promoting in place " \
+ "is that less work is required by the GC at the time the " \
+ "region is promoted. A disadvantage of promoting in place " \
+ "is that this introduces fragmentation of old-gen memory, " \
+ "with old-gen regions scattered throughout the heap. Regions " \
+ "that have been promoted in place may need to be evacuated at " \
+ "a later time in order to compact old-gen memory to enable " \
+ "future humongous allocations.") \
+ range(0,100) \
+ \
product(uintx, ShenandoahGenerationalHumongousReserve, 0, EXPERIMENTAL, \
"(Generational mode only) What percent of the heap should be " \
"reserved for humongous objects if possible. Old-generation " \
@@ -165,7 +179,7 @@
"collector accepts. In percents of heap region size.") \
range(0,100) \
\
- product(uintx, ShenandoahOldGarbageThreshold, 15, EXPERIMENTAL, \
+ product(uintx, ShenandoahOldGarbageThreshold, 25, EXPERIMENTAL, \
"How much garbage an old region has to contain before it would " \
"be taken for collection.") \
range(0,100) \
From 000569da601afde85f83c361c9f1a7ba3814bff4 Mon Sep 17 00:00:00 2001
From: Ioi Lam
Date: Thu, 18 Sep 2025 16:09:26 +0000
Subject: [PATCH 039/664] 8362561: Remove diagnostic option
AllowArchivingWithJavaAgent
Reviewed-by: sspitsyn, shade, dholmes, ayang
---
src/hotspot/share/cds/aotMetaspace.cpp | 5 -
src/hotspot/share/cds/cdsConfig.cpp | 11 --
src/hotspot/share/cds/cds_globals.hpp | 4 -
src/hotspot/share/cds/dynamicArchive.cpp | 5 -
src/hotspot/share/cds/filemap.cpp | 17 ---
src/hotspot/share/cds/filemap.hpp | 1 -
src/hotspot/share/classfile/classLoader.cpp | 18 ---
src/hotspot/share/prims/jvmtiAgent.cpp | 19 +--
test/hotspot/jtreg/TEST.groups | 9 --
.../cds/appcds/LambdaWithJavaAgent.java | 95 -------------
.../appcds/TransformInterfaceOfLambda.java | 80 -----------
.../cds/appcds/aotCache/JavaAgent.java | 57 ++++++--
.../RedefineCallerClassTest.java | 108 ---------------
...ExceptionDuringDumpAtObjectsInitPhase.java | 87 ------------
.../cds/appcds/javaldr/GCDuringDump.java | 85 ------------
.../javaldr/GCSharedStringsDuringDump.java | 130 ------------------
.../cds/appcds/javaldr/LockDuringDump.java | 83 -----------
.../jvmti/dumpingWithAgent/AppWithBMH.java | 34 -----
.../DumpingWithJavaAgent.java | 129 -----------------
.../DumpingWithJvmtiAgent.java | 66 ---------
.../OldClassWithJavaAgent.java | 61 --------
.../jvmti/dumpingWithAgent/SimpleAgent.java | 52 -------
.../jvmti/dumpingWithAgent/SimpleAgent.mf | 2 -
.../libAddToSystemCLSearchOnLoad.c | 48 -------
.../OldClassAndRedefineClass.java | 3 +-
25 files changed, 52 insertions(+), 1157 deletions(-)
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDump.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/AppWithBMH.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJavaAgent.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJvmtiAgent.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/OldClassWithJavaAgent.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.java
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.mf
delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/libAddToSystemCLSearchOnLoad.c
diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp
index 341371ad6bc..51227768293 100644
--- a/src/hotspot/share/cds/aotMetaspace.cpp
+++ b/src/hotspot/share/cds/aotMetaspace.cpp
@@ -1076,11 +1076,6 @@ bool AOTMetaspace::write_static_archive(ArchiveBuilder* builder, FileMapInfo* ma
return false;
}
builder->write_archive(map_info, heap_info);
-
- if (AllowArchivingWithJavaAgent) {
- aot_log_warning(aot)("This %s was created with AllowArchivingWithJavaAgent. It should be used "
- "for testing purposes only and should not be used in a production environment", CDSConfig::type_of_archive_being_loaded());
- }
return true;
}
diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp
index 20bf6b0d67c..5bb46deb9bc 100644
--- a/src/hotspot/share/cds/cdsConfig.cpp
+++ b/src/hotspot/share/cds/cdsConfig.cpp
@@ -470,10 +470,6 @@ void CDSConfig::check_aot_flags() {
assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc");
check_aotmode_create();
}
-
- // This is an old flag used by CDS regression testing only. It doesn't apply
- // to the AOT workflow.
- FLAG_SET_ERGO(AllowArchivingWithJavaAgent, false);
}
void CDSConfig::check_aotmode_off() {
@@ -716,13 +712,6 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
}
}
- if (is_dumping_classic_static_archive() && AOTClassLinking) {
- if (JvmtiAgentList::disable_agent_list()) {
- FLAG_SET_ERGO(AllowArchivingWithJavaAgent, false);
- log_warning(cds)("Disabled all JVMTI agents with -Xshare:dump -XX:+AOTClassLinking");
- }
- }
-
return true;
}
diff --git a/src/hotspot/share/cds/cds_globals.hpp b/src/hotspot/share/cds/cds_globals.hpp
index f4094aec1ac..3e3062097f9 100644
--- a/src/hotspot/share/cds/cds_globals.hpp
+++ b/src/hotspot/share/cds/cds_globals.hpp
@@ -63,10 +63,6 @@
"Average number of symbols per bucket in shared table") \
range(2, 246) \
\
- product(bool, AllowArchivingWithJavaAgent, false, DIAGNOSTIC, \
- "Allow Java agent to be run with CDS dumping (not applicable" \
- " to AOT") \
- \
develop(ccstr, ArchiveHeapTestClass, nullptr, \
"For JVM internal testing only. The static field named " \
"\"archivedObjects\" of the specified class is stored in the " \
diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp
index 0ba911b41bb..dd24f1e0c51 100644
--- a/src/hotspot/share/cds/dynamicArchive.cpp
+++ b/src/hotspot/share/cds/dynamicArchive.cpp
@@ -395,11 +395,6 @@ public:
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
void doit() {
ResourceMark rm;
- if (AllowArchivingWithJavaAgent) {
- aot_log_warning(aot)("This %s was created with AllowArchivingWithJavaAgent. It should be used "
- "for testing purposes only and should not be used in a production environment",
- CDSConfig::type_of_archive_being_loaded());
- }
AOTClassLocationConfig::dumptime_check_nonempty_dirs();
_builder.doit();
}
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 409052eae6a..8c2175622e9 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -259,7 +259,6 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
_has_platform_or_app_classes = AOTClassLocationConfig::dumptime()->has_platform_or_app_classes();
_requested_base_address = (char*)SharedBaseAddress;
_mapped_base_address = (char*)SharedBaseAddress;
- _allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
}
void FileMapHeader::copy_base_archive_name(const char* archive) {
@@ -316,7 +315,6 @@ void FileMapHeader::print(outputStream* st) {
st->print_cr("- _heap_ptrmap_start_pos: %zu", _heap_ptrmap_start_pos);
st->print_cr("- _rw_ptrmap_start_pos: %zu", _rw_ptrmap_start_pos);
st->print_cr("- _ro_ptrmap_start_pos: %zu", _ro_ptrmap_start_pos);
- st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling);
st->print_cr("- has_full_module_graph %d", _has_full_module_graph);
st->print_cr("- has_aot_linked_classes %d", _has_aot_linked_classes);
@@ -2051,21 +2049,6 @@ bool FileMapHeader::validate() {
_has_platform_or_app_classes = false;
}
- // Java agents are allowed during run time. Therefore, the following condition is not
- // checked: (!_allow_archiving_with_java_agent && AllowArchivingWithJavaAgent)
- // Note: _allow_archiving_with_java_agent is set in the shared archive during dump time
- // while AllowArchivingWithJavaAgent is set during the current run.
- if (_allow_archiving_with_java_agent && !AllowArchivingWithJavaAgent) {
- AOTMetaspace::report_loading_error("The setting of the AllowArchivingWithJavaAgent is different "
- "from the setting in the %s.", file_type);
- return false;
- }
-
- if (_allow_archiving_with_java_agent) {
- aot_log_warning(aot)("This %s was created with AllowArchivingWithJavaAgent. It should be used "
- "for testing purposes only and should not be used in a production environment", file_type);
- }
-
aot_log_info(aot)("The %s was created with UseCompressedOops = %d, UseCompressedClassPointers = %d, UseCompactObjectHeaders = %d",
file_type, compressed_oops(), compressed_class_pointers(), compact_headers());
if (compressed_oops() != UseCompressedOops || compressed_class_pointers() != UseCompressedClassPointers) {
diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp
index b40e793a0fd..a58271eefc7 100644
--- a/src/hotspot/share/cds/filemap.hpp
+++ b/src/hotspot/share/cds/filemap.hpp
@@ -135,7 +135,6 @@ private:
char* _requested_base_address; // Archive relocation is not necessary if we map with this base address.
char* _mapped_base_address; // Actual base address where archive is mapped.
- bool _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option
bool _use_optimized_module_handling;// No module-relation VM options were specified, so we can skip
// some expensive operations.
bool _has_aot_linked_classes; // Was the CDS archive created with -XX:+AOTClassLinking
diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
index 1f2eb6d25cc..3c7f6f8130e 100644
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.cpp
@@ -1306,24 +1306,6 @@ void ClassLoader::record_result_for_builtin_loader(s2 classpath_index, InstanceK
AOTClassLocationConfig::dumptime_update_max_used_index(classpath_index);
result->set_shared_classpath_index(classpath_index);
-
-#if INCLUDE_CDS_JAVA_HEAP
- if (CDSConfig::is_dumping_heap() && AllowArchivingWithJavaAgent && result->defined_by_boot_loader() &&
- classpath_index < 0 && redefined) {
- // When dumping the heap (which happens only during static dump), classes for the built-in
- // loaders are always loaded from known locations (jimage, classpath or modulepath),
- // so classpath_index should always be >= 0.
- // The only exception is when a java agent is used during dump time (for testing
- // purposes only). If a class is transformed by the agent, the AOTClassLocation of
- // this class may point to an unknown location. This may break heap object archiving,
- // which requires all the boot classes to be from known locations. This is an
- // uncommon scenario (even in test cases). Let's simply disable heap object archiving.
- ResourceMark rm;
- log_warning(aot)("heap objects cannot be written because class %s maybe modified by ClassFileLoadHook.",
- result->external_name());
- CDSConfig::disable_heap_dumping();
- }
-#endif // INCLUDE_CDS_JAVA_HEAP
}
void ClassLoader::record_hidden_class(InstanceKlass* ik) {
diff --git a/src/hotspot/share/prims/jvmtiAgent.cpp b/src/hotspot/share/prims/jvmtiAgent.cpp
index 16a47042a69..66cb68b44b0 100644
--- a/src/hotspot/share/prims/jvmtiAgent.cpp
+++ b/src/hotspot/share/prims/jvmtiAgent.cpp
@@ -576,25 +576,14 @@ static bool invoke_Agent_OnAttach(JvmtiAgent* agent, outputStream* st) {
}
#if INCLUDE_CDS
-// CDS dumping does not support native JVMTI agent.
-// CDS dumping supports Java agent if the AllowArchivingWithJavaAgent diagnostic option is specified.
static void check_cds_dump(JvmtiAgent* agent) {
if (CDSConfig::new_aot_flags_used()) { // JEP 483
// Agents are allowed with -XX:AOTMode=record and -XX:AOTMode=on/auto.
- // Agents are completely disabled when -XX:AOTMode=create
+ // Agents are completely disabled when -XX:AOTMode=create (see cdsConfig.cpp)
assert(!CDSConfig::is_dumping_final_static_archive(), "agents should have been disabled with -XX:AOTMode=create");
- return;
- }
-
- // This is classic CDS limitations -- we disallow agents by default. They can be used
- // with -XX:+AllowArchivingWithJavaAgent, but that should be used for diagnostic purposes only.
- assert(agent != nullptr, "invariant");
- if (!agent->is_instrument_lib()) {
- vm_exit_during_cds_dumping("CDS dumping does not support native JVMTI agent, name", agent->name());
- }
- if (!AllowArchivingWithJavaAgent) {
- vm_exit_during_cds_dumping(
- "Must enable AllowArchivingWithJavaAgent in order to run Java agent during CDS dumping");
+ } else if (CDSConfig::is_dumping_classic_static_archive() || CDSConfig::is_dumping_dynamic_archive()) {
+ // Classic CDS (static or dynamic dump). Disallow agents.
+ vm_exit_during_cds_dumping("JVMTI agents are not allowed when dumping CDS archives");
}
}
#endif // INCLUDE_CDS
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index 18cd93d4856..8169ca87f4e 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -427,9 +427,6 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java \
-runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java \
-runtime/cds/appcds/javaldr/ArrayTest.java \
- -runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java \
- -runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java \
- -runtime/cds/appcds/javaldr/LockDuringDump.java \
-runtime/cds/appcds/jcmd/JCmdTestStaticDump.java \
-runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java \
-runtime/cds/appcds/jcmd/JCmdTestFileSafety.java \
@@ -451,7 +448,6 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/LambdaInvokeVirtual.java \
-runtime/cds/appcds/LambdaProxyClasslist.java \
-runtime/cds/appcds/LambdaVerificationFailedDuringDump.java \
- -runtime/cds/appcds/LambdaWithJavaAgent.java \
-runtime/cds/appcds/LambdaWithUseImplMethodHandle.java \
-runtime/cds/appcds/LambdaWithOldClass.java \
-runtime/cds/appcds/LongClassListPath.java \
@@ -495,7 +491,6 @@ hotspot_cds_verify_shared_spaces = \
runtime/cds/appcds/customLoader/LoaderSegregationTest.java \
runtime/cds/appcds/javaldr/ArrayTest.java \
runtime/cds/appcds/jigsaw/modulepath/ExportModule.java \
- runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJavaAgent.java \
runtime/cds/appcds/sharedStrings/SharedStringsBasic.java
# No need to run every test with EpsilonGC. A small subset will provide enough
@@ -536,9 +531,6 @@ hotspot_aot_classlinking = \
-runtime/cds/appcds/DumpClassListWithLF.java \
-runtime/cds/appcds/dynamicArchive \
-runtime/cds/appcds/HelloExtTest.java \
- -runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java \
- -runtime/cds/appcds/javaldr/GCDuringDump.java \
- -runtime/cds/appcds/javaldr/LockDuringDump.java \
-runtime/cds/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java \
-runtime/cds/appcds/jigsaw/ExactOptionMatch.java \
-runtime/cds/appcds/jigsaw/JigsawOptionsCombo.java \
@@ -554,7 +546,6 @@ hotspot_aot_classlinking = \
-runtime/cds/appcds/JvmtiAddPath.java \
-runtime/cds/appcds/jvmti \
-runtime/cds/appcds/LambdaProxyClasslist.java \
- -runtime/cds/appcds/LambdaWithJavaAgent.java \
-runtime/cds/appcds/loaderConstraints/LoaderConstraintsTest.java \
-runtime/cds/appcds/methodHandles \
-runtime/cds/appcds/NestHostOldInf.java \
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java
deleted file mode 100644
index accb74025ce..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @bug 8276126
- * @summary Test static dumping with java agent transforming a class loaded
- * by the boot class loader.
- * @requires vm.cds.write.archived.java.heap
- * @requires vm.jvmti
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @compile test-classes/Hello.java
- * @compile test-classes/TransformBootClass.java
- * @run driver LambdaWithJavaAgent
- */
-
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.cds.CDSTestUtils;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class LambdaWithJavaAgent {
-
- public static String agentClasses[] = {
- TransformBootClass.class.getName(),
- };
-
- public static void main(String[] args) throws Exception {
- String mainClass = Hello.class.getName();
- String namePrefix = "lambda-with-java-agent";
- JarBuilder.build(namePrefix, mainClass);
-
- String appJar = TestCommon.getTestJar(namePrefix + ".jar");
- String classList = namePrefix + ".list";
- String archiveName = namePrefix + ".jsa";
-
- String agentJar =
- ClassFileInstaller.writeJar("TransformBootClass.jar",
- ClassFileInstaller.Manifest.fromSourceFile("test-classes/TransformBootClass.mf"),
- agentClasses);
- String useJavaAgent = "-javaagent:" + agentJar + "=jdk/internal/math/FDBigInteger";
-
- // dump class list
- CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass);
-
- // create archive with the class list
- CDSOptions opts = (new CDSOptions())
- .addPrefix("-XX:ExtraSharedClassListFile=" + classList,
- "-cp", appJar,
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- useJavaAgent,
- "-Xlog:class+load,cds+class=debug,aot,cds")
- .setArchiveName(archiveName);
- OutputAnalyzer output = CDSTestUtils.createArchiveAndCheck(opts);
- output.shouldContain("heap objects cannot be written because class jdk.internal.math.FDBigInteger maybe modified by ClassFileLoadHook")
- .shouldContain("Skipping jdk/internal/math/FDBigInteger: Unsupported location")
- .shouldMatch(".class.load.*jdk.internal.math.FDBigInteger.*source.*modules");
-
- // run with archive
- CDSOptions runOpts = (new CDSOptions())
- .addPrefix("-cp", appJar, "-Xlog:class+load=debug,aot=debug,cds=debug,class+path=debug",
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- useJavaAgent)
- .setArchiveName(archiveName)
- .setUseVersion(false)
- .addSuffix(mainClass);
- output = CDSTestUtils.runWithArchive(runOpts);
- TestCommon.checkExecReturn(output, 0, true,
- "Hello source: shared objects file");
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java b/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java
deleted file mode 100644
index 88620fc039f..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/TransformInterfaceOfLambda.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @bug 8323950
- * @summary Transforming an interface of an archived lambda proxy class should not
- * crash the VM. The lambda proxy class should be regenerated during runtime.
- * @requires vm.cds
- * @requires vm.cds.default.archive.available
- * @requires vm.jvmti
- * @requires vm.flagless
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @compile test-classes/SimpleTest.java
- * @compile test-classes/TransformBootClass.java
- * @run driver TransformInterfaceOfLambda
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class TransformInterfaceOfLambda {
-
- public static String agentClasses[] = {
- TransformBootClass.class.getName(),
- };
-
- public static void main(String[] args) throws Exception {
- String mainClass = SimpleTest.class.getName();
- String namePrefix = "transform-interface-of-lambda";
- JarBuilder.build(namePrefix, mainClass);
-
- String appJar = TestCommon.getTestJar(namePrefix + ".jar");
-
- String agentJar =
- ClassFileInstaller.writeJar("TransformBootClass.jar",
- ClassFileInstaller.Manifest.fromSourceFile("test-classes/TransformBootClass.mf"),
- agentClasses);
- String useJavaAgent = "-javaagent:" + agentJar + "=java/util/function/IntFunction";
-
- ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
- "-cp", appJar, "-Xlog:class+load,cds=debug",
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- useJavaAgent,
- mainClass);
- OutputAnalyzer out = new OutputAnalyzer(pb.start());
- System.out.println(out.getStdout());
- out.shouldHaveExitValue(0)
- // the class loaded by the SimpleTest should be from the archive
- .shouldContain("[class,load] java.text.SimpleDateFormat source: shared objects file")
- // the IntFunction is the interface which is being transformed. The
- // interface is a super type of the following lambda proxy class.
- .shouldContain("Transforming class java/util/function/IntFunction")
- // the lambda proxy class should be regenerated
- .shouldMatch(".class.load.*sun.util.locale.provider.LocaleProviderAdapter[$][$]Lambda/0x.*source:.*sun.util.locale.provider.LocaleProviderAdapter");
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
index a0feb76a910..491a5bf1fa7 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
@@ -26,7 +26,7 @@
/*
* @test id=static
* @bug 8361725
- * @summary -javaagent should be disabled with -Xshare:dump -XX:+AOTClassLinking
+ * @summary -javaagent is not allowed when creating static CDS archive
* @requires vm.cds.supports.aot.class.linking
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* @build JavaAgent JavaAgentTransformer Util
@@ -34,6 +34,18 @@
* @run driver JavaAgent STATIC
*/
+/**
+ * @test id=dynamic
+ * @bug 8362561
+ * @summary -javaagent is not allowed when creating dynamic CDS archive
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * @build JavaAgent JavaAgentTransformer Util
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar JavaAgentApp JavaAgentApp$ShouldBeTransformed
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. JavaAgent DYNAMIC
+ */
+
/*
* @test id=aot
* @summary -javaagent should be allowed in AOT workflow. However, classes transformed/redefined by agents will not
@@ -64,7 +76,13 @@ public class JavaAgent {
ClassFileInstaller.Manifest.fromSourceFile("JavaAgentTransformer.mf"),
agentClasses);
- new Tester().run(args);
+ Tester t = new Tester();
+ if (args[0].equals("STATIC") || args[0].equals("DYNAMIC")) {
+ // Some child processes may have non-zero exits. These are checked by
+ // checkExecutionForStaticWorkflow() and checkExecutionForDynamicWorkflow
+ t.setCheckExitValue(false);
+ }
+ t.run(args);
}
static class Tester extends CDSAppTester {
@@ -80,8 +98,6 @@ public class JavaAgent {
@Override
public String[] vmArgs(RunMode runMode) {
return new String[] {
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
"-javaagent:" + agentJar,
"-Xlog:aot,cds",
"-XX:+AOTClassLinking",
@@ -99,8 +115,10 @@ public class JavaAgent {
public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {
if (isAOTWorkflow()) {
checkExecutionForAOTWorkflow(out, runMode);
- } else {
+ } else if (isStaticWorkflow()) {
checkExecutionForStaticWorkflow(out, runMode);
+ } else {
+ checkExecutionForDynamicWorkflow(out, runMode);
}
}
@@ -133,12 +151,31 @@ public class JavaAgent {
public void checkExecutionForStaticWorkflow(OutputAnalyzer out, RunMode runMode) throws Exception {
switch (runMode) {
- case RunMode.DUMP_STATIC:
- out.shouldContain("Disabled all JVMTI agents with -Xshare:dump -XX:+AOTClassLinking");
- out.shouldNotContain(agentPremainFinished);
- break;
- default:
+ case RunMode.TRAINING:
out.shouldContain(agentPremainFinished);
+ out.shouldHaveExitValue(0);
+ break;
+ case RunMode.DUMP_STATIC:
+ out.shouldContain("JVMTI agents are not allowed when dumping CDS archives");
+ out.shouldNotHaveExitValue(0);
+ break;
+ case RunMode.PRODUCTION:
+ out.shouldContain("Unable to use shared archive: invalid archive");
+ out.shouldNotHaveExitValue(0);
+ break;
+ }
+ }
+
+ public void checkExecutionForDynamicWorkflow(OutputAnalyzer out, RunMode runMode) throws Exception {
+ switch (runMode) {
+ case RunMode.DUMP_DYNAMIC:
+ out.shouldContain("JVMTI agents are not allowed when dumping CDS archives");
+ out.shouldNotHaveExitValue(0);
+ break;
+ case RunMode.PRODUCTION:
+ out.shouldContain("Unable to use shared archive: invalid archive");
+ out.shouldNotHaveExitValue(0);
+ break;
}
}
}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java
deleted file mode 100644
index 90d403bc380..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @bug 8276184
- * @summary If the caller class is redefined during dump time, the caller class
- * and its lambda proxy class should not be archived.
- * @requires vm.cds
- * @requires vm.jvmti
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
- * /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
- * @build jdk.test.whitebox.WhiteBox OldProvider
- * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
- * @run driver RedefineClassHelper
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. RedefineCallerClassTest
- */
-
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class RedefineCallerClassTest extends DynamicArchiveTestBase {
- static String mainClass = RedefineCallerClass.class.getName();
-
- static String providerClass = OldProvider.class.getName();
-
- static String sharedClasses[] = {
- mainClass,
- "SimpleLambda", // caller class will be redefined in RedefineCallerClass
- providerClass, // inteface with class file major version < 50
- "jdk/test/lib/compiler/InMemoryJavaCompiler",
- "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper",
- "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1",
- "jdk/test/lib/compiler/InMemoryJavaCompiler$SourceFile",
- "jdk/test/lib/compiler/InMemoryJavaCompiler$ClassFile"
- };
-
- public static void main(String[] args) throws Exception {
- runTest(RedefineCallerClassTest::test);
- }
-
- static void test() throws Exception {
- String topArchiveName = getNewArchiveName();
- String appJar = ClassFileInstaller.writeJar("redefine_caller_class.jar", sharedClasses);
-
- String[] mainArgs = {
- "redefineCaller", // redefine caller class only
- "useOldInf", // use old interface only
- "both" // both of the above
- };
-
- for (String mainArg : mainArgs) {
- String[] options = {
- "-Xlog:class+load,cds",
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- "-javaagent:redefineagent.jar",
- "-cp", appJar, mainClass, mainArg
- };
-
- dump(topArchiveName, options)
- .assertNormalExit(output -> {
- output.shouldHaveExitValue(0);
- if (mainArg.equals("both") || mainArg.equals("useOldInf")) {
- output.shouldContain("Skipping OldProvider: Old class has been linked")
- .shouldMatch("Skipping.SimpleLambda[$][$]Lambda.*0x.*:.*Old.class.has.been.linked");
- }
- if (mainArg.equals("both") || mainArg.equals("redefineCaller")) {
- output.shouldContain("Skipping SimpleLambda: Has been redefined");
- }
- });
-
- run(topArchiveName, options)
- .assertNormalExit(output -> {
- output.shouldHaveExitValue(0)
- .shouldContain("RedefineCallerClass source: shared objects file (top)")
- .shouldMatch(".class.load. SimpleLambda[$][$]Lambda.*/0x.*source:.*SimpleLambda");
- if (mainArg.equals("both") || mainArg.equals("useOldInf")) {
- output.shouldMatch(".class.load. OldProvider.source:.*redefine_caller_class.jar");
- }
- if (mainArg.equals("both") || mainArg.equals("redefineCaller")) {
- output.shouldMatch(".class.load. SimpleLambda.source:.*redefine_caller_class.jar");
- }
- });
- }
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java
deleted file mode 100644
index 5d9ef9ef760..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/ExceptionDuringDumpAtObjectsInitPhase.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary Out of memory When dumping the CDS archive
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @requires vm.cds.write.archived.java.heap
- * @requires vm.jvmti
- * @run driver ExceptionDuringDumpAtObjectsInitPhase
- */
-
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class ExceptionDuringDumpAtObjectsInitPhase {
- public static String appClasses[] = {
- Hello.class.getName(),
- };
- public static String agentClasses[] = {
- GCDuringDumpTransformer.class.getName(),
- GCDuringDumpTransformer.MyCleaner.class.getName(),
- };
-
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("GCDuringDumpTransformer.jar",
- ClassFileInstaller.Manifest.fromSourceFile("GCDuringDumpTransformer.mf"),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("GCDuringDumpApp.jar", appClasses);
-
- String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
- "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
-
- // 1. Test with exception
- System.out.println("1. Exception during dump");
- TestCommon.dump(appJar,
- TestCommon.list(Hello.class.getName()),
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- "-javaagent:" + agentJar,
- "-Xlog:cds,class+load",
- "-Xmx32m",
- "-Dtest.with.exception=true",
- gcLog).shouldNotHaveExitValue(0)
- .shouldContain("Preload Warning: Cannot find jdk/internal/math/FDBigInteger")
- .shouldContain("Unexpected exception, use -Xlog:aot,cds,exceptions=trace for detail");
-
- // 2. Test with OOM
- System.out.println("2. OOM during dump");
- TestCommon.dump(appJar,
- TestCommon.list(Hello.class.getName()),
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
- "-javaagent:" + agentJar,
- "-Dtest.with.oom=true",
- "-Xlog:cds,class+load",
- "-Xmx12M",
- gcLog).shouldNotHaveExitValue(0)
- .shouldContain("Out of memory. Please run with a larger Java heap, current MaxHeapSize");
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDump.java
deleted file mode 100644
index dd57c7efa2e..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDump.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary When dumping the CDS archive, try to cause garbage collection while classes are being loaded.
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @requires vm.cds
- * @requires vm.jvmti
- * @run driver GCDuringDump
- */
-
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class GCDuringDump {
- public static String appClasses[] = {
- Hello.class.getName(),
- };
- public static String agentClasses[] = {
- GCDuringDumpTransformer.class.getName(),
- GCDuringDumpTransformer.MyCleaner.class.getName(),
- };
-
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("GCDuringDumpTransformer.jar",
- ClassFileInstaller.Manifest.fromSourceFile("GCDuringDumpTransformer.mf"),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("GCDuringDumpApp.jar", appClasses);
-
- String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
- "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
-
- for (int i=0; i<3; i++) {
- // i = 0 -- run without agent = no extra GCs
- // i = 1 -- run with agent = cause extra GCs
- // i = 2 -- run with agent = cause extra GCs + use java.lang.ref.Cleaner
-
- String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
- String extraOption = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
- String extraOption2 = (i != 2) ? "-showversion" : "-Dtest.with.cleaner=true";
-
- TestCommon.testDump(appJar, TestCommon.list(Hello.class.getName()),
- "-XX:+UnlockDiagnosticVMOptions", extraOption, extraOption2,
- "-Xlog:exceptions=trace",
- extraArg, "-Xmx32m", gcLog);
-
- TestCommon.run(
- "-cp", appJar,
- "-Xmx32m",
- "-Xlog:cds=info",
- "-XX:+UnlockDiagnosticVMOptions", extraOption,
- gcLog,
- Hello.class.getName())
- .assertNormalExit();
- }
- }
-}
-
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java
deleted file mode 100644
index 1dac0149964..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary Similar to GCDuringDumping.java, this test adds the -XX:SharedArchiveConfigFile
- * option for testing the interaction with GC and shared strings.
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @requires vm.cds.write.archived.java.heap
- * @requires vm.jvmti
- * @build jdk.test.whitebox.WhiteBox
- * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
- * @run driver/timeout=480 GCSharedStringsDuringDump
- */
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.cds.CDSTestUtils;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class GCSharedStringsDuringDump {
- static {
- // EpsilonGC will run out of memory.
- CDSOptions.disableRuntimePrefixForEpsilonGC();
- }
- public static String appClasses[] = {
- GCSharedStringsDuringDumpWb.class.getName(),
- };
- public static String agentClasses[] = {
- GCDuringDumpTransformer.class.getName(),
- };
-
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("GCDuringDumpTransformer.jar",
- ClassFileInstaller.Manifest.fromSourceFile("GCDuringDumpTransformer.mf"),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("GCSharedStringsDuringDumpApp.jar", appClasses);
-
- String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
- "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
-
- String sharedArchiveCfgFile =
- CDSTestUtils.getOutputDir() + File.separator + "GCSharedStringDuringDump_gen.txt";
- try (FileOutputStream fos = new FileOutputStream(sharedArchiveCfgFile)) {
- PrintWriter out = new PrintWriter(new OutputStreamWriter(fos));
- out.println("VERSION: 1.0");
- out.println("@SECTION: String");
- out.println("31: shared_test_string_unique_14325");
- for (int i=0; i<100000; i++) {
- String s = "generated_string " + i;
- out.println(s.length() + ": " + s);
- }
- out.close();
- }
-
- JarBuilder.build(true, "WhiteBox", "jdk/test/whitebox/WhiteBox");
- String whiteBoxJar = TestCommon.getTestJar("WhiteBox.jar");
- String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar;
-
- for (int i=0; i<2; i++) {
- // i = 0 -- run without agent = no extra GCs
- // i = 1 -- run with agent = cause extra GCs
-
- String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
- String extraOption = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
- OutputAnalyzer output = TestCommon.dump(
- appJar, TestCommon.list(GCSharedStringsDuringDumpWb.class.getName()),
- bootClassPath, extraArg, "-Xmx32m", gcLog,
- "-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile,
- "-XX:+UnlockDiagnosticVMOptions", extraOption);
-
- if (output.getStdout().contains("Too many string space regions") ||
- output.getStderr().contains("Unable to write archive heap memory regions") ||
- output.getStdout().contains("Try increasing NewSize") ||
- !output.getStdout().contains("oa0 space:") ||
- output.getExitValue() != 0) {
- // Try again with larger heap and NewSize, this should increase the
- // G1 heap region size to 2M
- TestCommon.testDump(
- appJar, TestCommon.list(GCSharedStringsDuringDumpWb.class.getName()),
- bootClassPath, extraArg, "-Xmx8g", "-XX:NewSize=8m", gcLog,
- "-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile,
- "-XX:+UnlockDiagnosticVMOptions", extraOption);
- }
-
- TestCommon.run(
- "-cp", appJar,
- bootClassPath,
- extraArg,
- "-Xlog:cds=info,class+path=info",
- "-Xmx32m",
- "-Xlog:cds=info",
- "-XX:+UnlockDiagnosticVMOptions",
- extraOption,
- "-XX:+WhiteBoxAPI",
- gcLog,
- GCSharedStringsDuringDumpWb.class.getName())
- .assertNormalExit();
- }
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
deleted file mode 100644
index 391596160d6..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @bug 8249276
- * @summary When dumping the CDS archive, try to lock some objects. These objects should be archived
- * without the locking bits in the markWord.
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
- * @requires vm.cds
- * @requires vm.jvmti
- * @modules java.instrument
- * @run driver LockDuringDump
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class LockDuringDump {
- public static String appClasses[] = {
- LockDuringDumpApp.class.getName(),
- };
- public static String agentClasses[] = {
- LockDuringDumpAgent.class.getName(),
- };
-
- private static final String MANIFEST =
- "Manifest-Version: 1.0\nPremain-Class: LockDuringDumpAgent\n";
-
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("LockDuringDumpAgent.jar",
- ClassFileInstaller.Manifest.fromString(MANIFEST),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("LockDuringDumpApp.jar", appClasses);
-
- for (int i = 0; i < 3; i++) {
- // i = 0 -- dump without agent
- // i = 1 -- dump with agent
-
- String agentArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
- String agentArg2 = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
-
- OutputAnalyzer out =
- TestCommon.testDump(appJar, TestCommon.list(LockDuringDumpApp.class.getName()),
- "-XX:+UnlockDiagnosticVMOptions",
- agentArg, agentArg2);
- if (i != 0 && !out.getStdout().contains("LockDuringDumpAgent timeout")) {
- out.shouldContain("Let's hold the lock on the literal string");
- }
-
- TestCommon.run(
- "-cp", appJar,
- "-XX:+UnlockDiagnosticVMOptions", agentArg2,
- LockDuringDumpApp.class.getName())
- .assertNormalExit("I am able to lock the literal string");
- }
- }
-}
-
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/AppWithBMH.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/AppWithBMH.java
deleted file mode 100644
index 7e08fd24cf6..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/AppWithBMH.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2024, 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.
- *
- */
-
-// Application which loads BoundMethodHandle species classes like the following:
-// java/lang/invoke/BoundMethodHandle$Species_LLLL
-import java.lang.management.ManagementFactory;
-
-public class AppWithBMH {
- public static void main(String[] args) {
- System.out.println("Hello world!");
- ManagementFactory.getGarbageCollectorMXBeans();
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJavaAgent.java
deleted file mode 100644
index 54cb3fb23fb..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJavaAgent.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary CDS dumping with java agent.
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @requires vm.cds
- * @requires vm.jvmti
- * @build SimpleAgent Hello AppWithBMH
- * @run main/othervm DumpingWithJavaAgent
- */
-
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class DumpingWithJavaAgent {
- public static String appClasses[] = {
- "Hello",
- "AppWithBMH",
- };
- public static String agentClasses[] = {
- "SimpleAgent",
- "SimpleAgent$1"
- };
-
- public static String warningMessages[] = {
- "This shared archive file was created with AllowArchivingWithJavaAgent",
- "It should be used for testing purposes only and should not be used in a production environment",
- };
-
- public static String errorMessage =
- "The setting of the AllowArchivingWithJavaAgent is different from the setting in the shared archive file.";
-
- public static String diagnosticOption = "-XX:+AllowArchivingWithJavaAgent";
-
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("SimpleAgent.jar",
- ClassFileInstaller.Manifest.fromSourceFile("SimpleAgent.mf"),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("DumpingWithJavaAgent.jar", appClasses);
-
- // CDS dumping with a java agent performing class transformation on BoundMethodHandle$Species classes
- OutputAnalyzer output = TestCommon.testDump(appJar, TestCommon.list("AppWithBMH"),
- "-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
- "-javaagent:" + agentJar + "=doTransform",
- "AppWithBMH");
- TestCommon.checkDump(output);
- output.shouldContain(warningMessages[0]);
- output.shouldContain(warningMessages[1]);
- output.shouldContain("inside SimpleAgent");
-
- // CDS dumping with a java agent with the AllowArchvingWithJavaAgent diagnostic option.
- output = TestCommon.testDump(appJar, TestCommon.list("Hello"),
- "-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
- "-javaagent:" + agentJar);
- TestCommon.checkDump(output);
- output.shouldContain(warningMessages[0]);
- output.shouldContain(warningMessages[1]);
- output.shouldContain("inside SimpleAgent");
-
- // Using the archive with the AllowArchvingWithJavaAgent diagnostic option.
- output = TestCommon.exec(
- appJar,
- "-Xlog:class+load=trace",
- "-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
- "Hello");
- if (!TestCommon.isUnableToMap(output)) {
- output.shouldHaveExitValue(0);
- output.shouldContain(warningMessages[0]);
- output.shouldContain(warningMessages[1]);
- output.shouldContain("[class,load] Hello source: shared objects file");
- }
-
- // Using the archive with -Xshare:on without the diagnostic option.
- // VM should exit with an error message.
- output = TestCommon.exec(
- appJar,
- "Hello");
- output.shouldHaveExitValue(1);
- output.shouldContain(errorMessage);
-
- // Using the archive with -Xshare:auto without the diagnostic option.
- // VM should continue execution with a warning message. The archive
- // will not be used.
- output = TestCommon.execAuto(
- "-cp", appJar,
- "-Xlog:class+load=trace,cds=info",
- "Hello");
- if (!TestCommon.isUnableToMap(output)) {
- output.shouldHaveExitValue(0);
- output.shouldContain(errorMessage);
- output.shouldMatch(".class.load.* Hello source:.*DumpingWithJavaAgent.jar");
-
- // CDS dumping with a java agent without the AllowArchvingWithJavaAgent diagnostic option.
- // VM will exit with an error message.
- output = TestCommon.dump(appJar, TestCommon.list("Hello"),
- "-javaagent:" + agentJar);
- }
- output.shouldContain("Must enable AllowArchivingWithJavaAgent in order to run Java agent during CDS dumping")
- .shouldHaveExitValue(1);
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJvmtiAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJvmtiAgent.java
deleted file mode 100644
index 9f3c5864f1b..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/DumpingWithJvmtiAgent.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @summary CDS dumping with JVMTI agent.
- * @requires vm.cds
- * @requires vm.jvmti
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
- * @compile ../../test-classes/Hello.java
- * @run main/othervm/native DumpingWithJvmtiAgent
- */
-
-import java.io.File;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class DumpingWithJvmtiAgent {
- private static final String AGENT_LIB_ONLOAD = "AddToSystemCLSearchOnLoad";
-
- public static void main(String[] args) throws Exception {
- String appJar = JarBuilder.getOrCreateHelloJar();
-
- // CDS dump with a JVMTI agent with the AllowArchivingWithJavaAgent option.
- // vm should exit with an error message.
- OutputAnalyzer out = TestCommon.dump(
- appJar,
- TestCommon.list("Hello"),
- "-XX:+UnlockDiagnosticVMOptions", "-XX:+AllowArchivingWithJavaAgent",
- "-agentlib:" + AGENT_LIB_ONLOAD + "=" + appJar,
- "-Djava.library.path=" + System.getProperty("java.library.path"));
- out.shouldContain("CDS dumping does not support native JVMTI agent, name: " + AGENT_LIB_ONLOAD)
- .shouldHaveExitValue(1);
-
- // CDS dump with a JVMTI agent without the AllowArchivingWithJavaAgent option.
- // vm should exit with an error message.
- out = TestCommon.dump(
- appJar,
- TestCommon.list("Hello"),
- "-agentlib:" + AGENT_LIB_ONLOAD + "=" + appJar,
- "-Djava.library.path=" + System.getProperty("java.library.path"));
- out.shouldContain("CDS dumping does not support native JVMTI agent, name: " + AGENT_LIB_ONLOAD)
- .shouldHaveExitValue(1);
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/OldClassWithJavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/OldClassWithJavaAgent.java
deleted file mode 100644
index a0a34eab9f9..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/OldClassWithJavaAgent.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-/*
- * @test
- * @bug 8261090
- * @summary Dump old class with java agent.
- * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
- * @requires vm.cds
- * @requires vm.jvmti
- * @compile ../../test-classes/OldSuper.jasm
- * @compile SimpleAgent.java
- * @run main/othervm OldClassWithJavaAgent
- */
-
-import jdk.test.lib.cds.CDSOptions;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.helpers.ClassFileInstaller;
-
-public class OldClassWithJavaAgent {
- public static String appClasses[] = {"OldSuper"};
- public static String agentClasses[] = {"SimpleAgent"};
- public static String diagnosticOption = "-XX:+AllowArchivingWithJavaAgent";
- public static void main(String[] args) throws Throwable {
- String agentJar =
- ClassFileInstaller.writeJar("SimpleAgent.jar",
- ClassFileInstaller.Manifest.fromSourceFile("SimpleAgent.mf"),
- agentClasses);
-
- String appJar =
- ClassFileInstaller.writeJar("OldClassWithJavaAgent.jar", appClasses);
- OutputAnalyzer output = TestCommon.testDump(appJar, TestCommon.list("OldSuper"),
- "-Xlog:cds=debug,class+load",
- "-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
- "-javaagent:" + agentJar + "=OldSuper");
-
- // The java agent will load and link the class. We will skip old classes
- // which have been linked during CDS dump.
- output.shouldContain("Skipping OldSuper: Old class has been linked");
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.java
deleted file mode 100644
index d280964c07d..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-
-public class SimpleAgent {
- public static void premain(String agentArg, Instrumentation instrumentation) throws Exception {
- System.out.println("inside SimpleAgent");
- if (agentArg == null) return;
- if (agentArg.equals("OldSuper")) {
- // Only load the class if the test requires it.
- Class> cls = Class.forName("OldSuper", true, ClassLoader.getSystemClassLoader());
- } else if (agentArg.equals("doTransform")) {
- ClassFileTransformer transformer = new ClassFileTransformer() {
- @Override
- public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
- if (loader == SimpleAgent.class.getClassLoader()) {
- // Transform only classes loaded by the apploader.
- System.out.printf("%n Transforming %s", className);
- return Arrays.copyOf(classfileBuffer, classfileBuffer.length);
- } else {
- return null;
- }
- }
- };
- instrumentation.addTransformer(transformer);
- }
- }
-}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.mf b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.mf
deleted file mode 100644
index f53b5299627..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/SimpleAgent.mf
+++ /dev/null
@@ -1,2 +0,0 @@
-Manifest-Version: 1.0
-Premain-Class: SimpleAgent
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/libAddToSystemCLSearchOnLoad.c b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/libAddToSystemCLSearchOnLoad.c
deleted file mode 100644
index 9d831f74936..00000000000
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/dumpingWithAgent/libAddToSystemCLSearchOnLoad.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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
-#include
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- static jvmtiEnv *jvmti = NULL;
-
- JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
- int err = (*jvm)->GetEnv(jvm, (void**) &jvmti, JVMTI_VERSION_9);
- if (err != JNI_OK) {
- return JNI_ERR;
- }
- err = (*jvmti)->AddToSystemClassLoaderSearch(jvmti, (const char*)options);
- if (err != JVMTI_ERROR_NONE) {
- return JNI_ERR;
- }
- return JNI_OK;
- }
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java
index 7581b2367aa..26bccdf764e 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, 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
@@ -67,7 +67,6 @@ public class OldClassAndRedefineClass {
out = TestCommon.exec(
appJar,
"-XX:+UnlockDiagnosticVMOptions",
- "-XX:+AllowArchivingWithJavaAgent",
"-XX:+WhiteBoxAPI",
"-Xlog:cds,class+load",
agentCmdArg,
From 14b9f53bb376c49b73b376c6e5a4b30105358b5a Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Thu, 18 Sep 2025 17:22:45 +0000
Subject: [PATCH 040/664] 8367626: Parallel: Remove
ParallelCompactData::summarize_dense_prefix
Reviewed-by: gli, fandreuzzi
---
.../share/gc/parallel/psParallelCompact.cpp | 35 +++----------------
.../share/gc/parallel/psParallelCompact.hpp | 5 ---
2 files changed, 5 insertions(+), 35 deletions(-)
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
index e63e189861f..dd8455104a9 100644
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
@@ -297,29 +297,6 @@ void ParallelCompactData::clear_range(size_t beg_region, size_t end_region) {
memset(_region_data + beg_region, 0, region_cnt * sizeof(RegionData));
}
-void
-ParallelCompactData::summarize_dense_prefix(HeapWord* beg, HeapWord* end)
-{
- assert(is_region_aligned(beg), "not RegionSize aligned");
- assert(is_region_aligned(end), "not RegionSize aligned");
-
- size_t cur_region = addr_to_region_idx(beg);
- const size_t end_region = addr_to_region_idx(end);
- HeapWord* addr = beg;
- while (cur_region < end_region) {
- _region_data[cur_region].set_destination(addr);
- _region_data[cur_region].set_destination_count(0);
- _region_data[cur_region].set_source_region(cur_region);
-
- // Update live_obj_size so the region appears completely full.
- size_t live_size = RegionSize - _region_data[cur_region].partial_obj_size();
- _region_data[cur_region].set_live_obj_size(live_size);
-
- ++cur_region;
- addr += RegionSize;
- }
-}
-
// The total live words on src_region would overflow the target space, so find
// the overflowing object and record the split point. The invariant is that an
// obj should not cross space boundary.
@@ -894,7 +871,6 @@ void PSParallelCompact::summary_phase(bool should_do_max_compaction)
if (dense_prefix_end != old_space->bottom()) {
fill_dense_prefix_end(id);
- _summary_data.summarize_dense_prefix(old_space->bottom(), dense_prefix_end);
}
// Compacting objs in [dense_prefix_end, old_space->top())
@@ -1539,17 +1515,16 @@ void PSParallelCompact::forward_to_new_addr() {
#ifdef ASSERT
void PSParallelCompact::verify_forward() {
HeapWord* const old_dense_prefix_addr = dense_prefix(SpaceId(old_space_id));
- RegionData* old_region = _summary_data.region(_summary_data.addr_to_region_idx(old_dense_prefix_addr));
- HeapWord* bump_ptr = old_region->partial_obj_size() != 0
- ? old_dense_prefix_addr + old_region->partial_obj_size()
- : old_dense_prefix_addr;
+ // The destination addr for the first live obj after dense-prefix.
+ HeapWord* bump_ptr = old_dense_prefix_addr
+ + _summary_data.addr_to_region_ptr(old_dense_prefix_addr)->partial_obj_size();
SpaceId bump_ptr_space = old_space_id;
for (uint id = old_space_id; id < last_space_id; ++id) {
MutableSpace* sp = PSParallelCompact::space(SpaceId(id));
- HeapWord* dense_prefix_addr = dense_prefix(SpaceId(id));
+ // Only verify objs after dense-prefix, because those before dense-prefix are not moved (forwarded).
+ HeapWord* cur_addr = dense_prefix(SpaceId(id));
HeapWord* top = sp->top();
- HeapWord* cur_addr = dense_prefix_addr;
while (cur_addr < top) {
cur_addr = mark_bitmap()->find_obj_beg(cur_addr, top);
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp
index d5ed641f485..4d212499b4c 100644
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp
@@ -360,11 +360,6 @@ public:
inline RegionData* region(size_t region_idx) const;
inline size_t region(const RegionData* const region_ptr) const;
- // Fill in the regions covering [beg, end) so that no data moves; i.e., the
- // destination of region n is simply the start of region n. Both arguments
- // beg and end must be region-aligned.
- void summarize_dense_prefix(HeapWord* beg, HeapWord* end);
-
HeapWord* summarize_split_space(size_t src_region, SplitInfo& split_info,
HeapWord* destination, HeapWord* target_end,
HeapWord** target_next);
From 4be4826ddb51c155eec3fe2923d891357f8d753b Mon Sep 17 00:00:00 2001
From: William Kemper
Date: Thu, 18 Sep 2025 18:50:44 +0000
Subject: [PATCH 041/664] 8367450: Shenandoah: Log the composition of the
collection set
Reviewed-by: ysr, kdnilsen, phh
---
.../shenandoahGenerationalHeuristics.cpp | 74 ++---------
.../shenandoahGenerationalHeuristics.hpp | 3 +-
.../heuristics/shenandoahGlobalHeuristics.cpp | 2 -
.../heuristics/shenandoahHeuristics.cpp | 22 +---
.../heuristics/shenandoahYoungHeuristics.cpp | 2 -
.../gc/shenandoah/shenandoahCollectionSet.cpp | 35 +++++
.../gc/shenandoah/shenandoahCollectionSet.hpp | 21 ++-
.../shenandoahCollectionSet.inline.hpp | 8 +-
.../gc/shenandoah/shenandoahEvacInfo.hpp | 120 ------------------
.../share/gc/shenandoah/shenandoahTrace.cpp | 36 +++---
.../share/gc/shenandoah/shenandoahTrace.hpp | 10 +-
11 files changed, 89 insertions(+), 244 deletions(-)
delete mode 100644 src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
index dfae9040242..c7067b2e5ab 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
@@ -26,7 +26,6 @@
#include "gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp"
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
-#include "gc/shenandoah/shenandoahEvacInfo.hpp"
#include "gc/shenandoah/shenandoahGeneration.hpp"
#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
@@ -185,59 +184,16 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio
heap->shenandoah_policy()->record_mixed_cycle();
}
- size_t cset_percent = (total_garbage == 0) ? 0 : (collection_set->garbage() * 100 / total_garbage);
- size_t collectable_garbage = collection_set->garbage() + immediate_garbage;
- size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
+ collection_set->summarize(total_garbage, immediate_garbage, immediate_regions);
- log_info(gc, ergo)("Collectable Garbage: %zu%s (%zu%%), "
- "Immediate: %zu%s (%zu%%), %zu regions, "
- "CSet: %zu%s (%zu%%), %zu regions",
-
- byte_size_in_proper_unit(collectable_garbage),
- proper_unit_for_byte_size(collectable_garbage),
- collectable_garbage_percent,
-
- byte_size_in_proper_unit(immediate_garbage),
- proper_unit_for_byte_size(immediate_garbage),
- immediate_percent,
- immediate_regions,
-
- byte_size_in_proper_unit(collection_set->garbage()),
- proper_unit_for_byte_size(collection_set->garbage()),
- cset_percent,
- collection_set->count());
-
- if (collection_set->garbage() > 0) {
- size_t young_evac_bytes = collection_set->get_young_bytes_reserved_for_evacuation();
- size_t promote_evac_bytes = collection_set->get_young_bytes_to_be_promoted();
- size_t old_evac_bytes = collection_set->get_old_bytes_reserved_for_evacuation();
- size_t total_evac_bytes = young_evac_bytes + promote_evac_bytes + old_evac_bytes;
- log_info(gc, ergo)("Evacuation Targets: YOUNG: %zu%s, "
- "PROMOTE: %zu%s, "
- "OLD: %zu%s, "
- "TOTAL: %zu%s",
- byte_size_in_proper_unit(young_evac_bytes), proper_unit_for_byte_size(young_evac_bytes),
- byte_size_in_proper_unit(promote_evac_bytes), proper_unit_for_byte_size(promote_evac_bytes),
- byte_size_in_proper_unit(old_evac_bytes), proper_unit_for_byte_size(old_evac_bytes),
- byte_size_in_proper_unit(total_evac_bytes), proper_unit_for_byte_size(total_evac_bytes));
-
- ShenandoahEvacuationInformation evacInfo;
- evacInfo.set_collection_set_regions(collection_set->count());
- evacInfo.set_collection_set_used_before(collection_set->used());
- evacInfo.set_collection_set_used_after(collection_set->live());
- evacInfo.set_collected_old(old_evac_bytes);
- evacInfo.set_collected_promoted(promote_evac_bytes);
- evacInfo.set_collected_young(young_evac_bytes);
- evacInfo.set_regions_promoted_humongous(humongous_regions_promoted);
- evacInfo.set_regions_promoted_regular(regular_regions_promoted_in_place);
- evacInfo.set_regular_promoted_garbage(regular_regions_promoted_garbage);
- evacInfo.set_regular_promoted_free(regular_regions_promoted_free);
- evacInfo.set_regions_immediate(immediate_regions);
- evacInfo.set_immediate_size(immediate_garbage);
- evacInfo.set_free_regions(free_regions);
-
- ShenandoahTracer().report_evacuation_info(&evacInfo);
- }
+ ShenandoahTracer::report_evacuation_info(collection_set,
+ free_regions,
+ humongous_regions_promoted,
+ regular_regions_promoted_in_place,
+ regular_regions_promoted_garbage,
+ regular_regions_promoted_free,
+ immediate_regions,
+ immediate_garbage);
}
@@ -268,15 +224,3 @@ size_t ShenandoahGenerationalHeuristics::add_preselected_regions_to_collection_s
return cur_young_garbage;
}
-void ShenandoahGenerationalHeuristics::log_cset_composition(ShenandoahCollectionSet* cset) const {
- size_t collected_old = cset->get_old_bytes_reserved_for_evacuation();
- size_t collected_promoted = cset->get_young_bytes_to_be_promoted();
- size_t collected_young = cset->get_young_bytes_reserved_for_evacuation();
-
- log_info(gc, ergo)(
- "Chosen CSet evacuates young: %zu%s (of which at least: %zu%s are to be promoted), "
- "old: %zu%s",
- byte_size_in_proper_unit(collected_young), proper_unit_for_byte_size(collected_young),
- byte_size_in_proper_unit(collected_promoted), proper_unit_for_byte_size(collected_promoted),
- byte_size_in_proper_unit(collected_old), proper_unit_for_byte_size(collected_old));
-}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
index 6708c63f042..31c016bb4b7 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
@@ -51,9 +51,8 @@ protected:
size_t add_preselected_regions_to_collection_set(ShenandoahCollectionSet* cset,
const RegionData* data,
size_t size) const;
-
- void log_cset_composition(ShenandoahCollectionSet* cset) const;
};
#endif //SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHGENERATIONALHEURISTICS_HPP
+
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
index 331bd040575..93f9b18ad9f 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
@@ -42,8 +42,6 @@ void ShenandoahGlobalHeuristics::choose_collection_set_from_regiondata(Shenandoa
QuickSort::sort(data, (int) size, compare_by_garbage);
choose_global_collection_set(cset, data, size, actual_free, 0 /* cur_young_garbage */);
-
- log_cset_composition(cset);
}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
index b151a75e6e7..c8a0c3dc518 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
@@ -153,27 +153,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec
choose_collection_set_from_regiondata(collection_set, candidates, cand_idx, immediate_garbage + free);
}
- size_t cset_percent = (total_garbage == 0) ? 0 : (collection_set->garbage() * 100 / total_garbage);
- size_t collectable_garbage = collection_set->garbage() + immediate_garbage;
- size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
-
- log_info(gc, ergo)("Collectable Garbage: %zu%s (%zu%%), "
- "Immediate: %zu%s (%zu%%), %zu regions, "
- "CSet: %zu%s (%zu%%), %zu regions",
-
- byte_size_in_proper_unit(collectable_garbage),
- proper_unit_for_byte_size(collectable_garbage),
- collectable_garbage_percent,
-
- byte_size_in_proper_unit(immediate_garbage),
- proper_unit_for_byte_size(immediate_garbage),
- immediate_percent,
- immediate_regions,
-
- byte_size_in_proper_unit(collection_set->garbage()),
- proper_unit_for_byte_size(collection_set->garbage()),
- cset_percent,
- collection_set->count());
+ collection_set->summarize(total_garbage, immediate_garbage, immediate_regions);
}
void ShenandoahHeuristics::record_cycle_start() {
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
index d236be8c9e6..15d1058d7cd 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
@@ -55,8 +55,6 @@ void ShenandoahYoungHeuristics::choose_collection_set_from_regiondata(Shenandoah
size_t cur_young_garbage = add_preselected_regions_to_collection_set(cset, data, size);
choose_young_collection_set(cset, data, size, actual_free, cur_young_garbage);
-
- log_cset_composition(cset);
}
void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollectionSet* cset,
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
index a58b9311183..745d45ace1e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
@@ -200,3 +200,38 @@ void ShenandoahCollectionSet::print_on(outputStream* out) const {
}
assert(regions == count(), "Must match");
}
+
+void ShenandoahCollectionSet::summarize(size_t total_garbage, size_t immediate_garbage, size_t immediate_regions) const {
+ const LogTarget(Info, gc, ergo) lt;
+ LogStream ls(lt);
+ if (lt.is_enabled()) {
+ const size_t cset_percent = (total_garbage == 0) ? 0 : (garbage() * 100 / total_garbage);
+ const size_t collectable_garbage = garbage() + immediate_garbage;
+ const size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
+ const size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage);
+
+ ls.print_cr("Collectable Garbage: " PROPERFMT " (%zu%%), "
+ "Immediate: " PROPERFMT " (%zu%%), %zu regions, "
+ "CSet: " PROPERFMT " (%zu%%), %zu regions",
+ PROPERFMTARGS(collectable_garbage),
+ collectable_garbage_percent,
+
+ PROPERFMTARGS(immediate_garbage),
+ immediate_percent,
+ immediate_regions,
+
+ PROPERFMTARGS(garbage()),
+ cset_percent,
+ count());
+
+ if (garbage() > 0) {
+ const size_t young_evac_bytes = get_young_bytes_reserved_for_evacuation();
+ const size_t promote_evac_bytes = get_young_bytes_to_be_promoted();
+ const size_t old_evac_bytes = get_old_bytes_reserved_for_evacuation();
+ const size_t total_evac_bytes = young_evac_bytes + promote_evac_bytes + old_evac_bytes;
+ ls.print_cr("Evacuation Targets: "
+ "YOUNG: " PROPERFMT ", " "PROMOTE: " PROPERFMT ", " "OLD: " PROPERFMT ", " "TOTAL: " PROPERFMT,
+ PROPERFMTARGS(young_evac_bytes), PROPERFMTARGS(promote_evac_bytes), PROPERFMTARGS(old_evac_bytes), PROPERFMTARGS(total_evac_bytes));
+ }
+ }
+}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
index 4f9f6fc2052..d4a590a3d89 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
@@ -103,17 +103,26 @@ public:
inline bool is_in(oop obj) const;
inline bool is_in_loc(void* loc) const;
+ // Prints a detailed accounting of all regions in the collection set when gc+cset=debug
void print_on(outputStream* out) const;
- // It is not known how many of these bytes will be promoted.
- inline size_t get_young_bytes_reserved_for_evacuation();
- inline size_t get_old_bytes_reserved_for_evacuation();
+ // Prints a summary of the collection set when gc+ergo=info
+ void summarize(size_t total_garbage, size_t immediate_garbage, size_t immediate_regions) const;
- inline size_t get_young_bytes_to_be_promoted();
+ // Returns the amount of live bytes in young regions in the collection set. It is not known how many of these bytes will be promoted.
+ inline size_t get_young_bytes_reserved_for_evacuation() const;
- size_t get_young_available_bytes_collected() { return _young_available_bytes_collected; }
+ // Returns the amount of live bytes in old regions in the collection set.
+ inline size_t get_old_bytes_reserved_for_evacuation() const;
- inline size_t get_old_garbage();
+ // Returns the amount of live bytes in young regions with an age above the tenuring threshold.
+ inline size_t get_young_bytes_to_be_promoted() const;
+
+ // Returns the amount of free bytes in young regions in the collection set.
+ size_t get_young_available_bytes_collected() const { return _young_available_bytes_collected; }
+
+ // Returns the amount of garbage in old regions in the collection set.
+ inline size_t get_old_garbage() const;
bool is_preselected(size_t region_idx) {
assert(_preselected_regions != nullptr, "Missing etsablish after abandon");
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
index 791e9c73b28..4adcec4fbb5 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
@@ -54,19 +54,19 @@ bool ShenandoahCollectionSet::is_in_loc(void* p) const {
return _biased_cset_map[index] == 1;
}
-size_t ShenandoahCollectionSet::get_old_bytes_reserved_for_evacuation() {
+size_t ShenandoahCollectionSet::get_old_bytes_reserved_for_evacuation() const {
return _old_bytes_to_evacuate;
}
-size_t ShenandoahCollectionSet::get_young_bytes_reserved_for_evacuation() {
+size_t ShenandoahCollectionSet::get_young_bytes_reserved_for_evacuation() const {
return _young_bytes_to_evacuate - _young_bytes_to_promote;
}
-size_t ShenandoahCollectionSet::get_young_bytes_to_be_promoted() {
+size_t ShenandoahCollectionSet::get_young_bytes_to_be_promoted() const {
return _young_bytes_to_promote;
}
-size_t ShenandoahCollectionSet::get_old_garbage() {
+size_t ShenandoahCollectionSet::get_old_garbage() const {
return _old_garbage;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp
deleted file mode 100644
index 8069fd13afa..00000000000
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright Amazon.com Inc. 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_SHENANDOAH_SHENANDOAHEVACINFO_HPP
-#define SHARE_GC_SHENANDOAH_SHENANDOAHEVACINFO_HPP
-
-#include "memory/allocation.hpp"
-
-class ShenandoahEvacuationInformation : public StackObj {
- // Values for ShenandoahEvacuationInformation jfr event, sizes stored as bytes
- size_t _collection_set_regions;
- size_t _collection_set_used_before;
- size_t _collection_set_used_after;
- size_t _collected_old;
- size_t _collected_promoted;
- size_t _collected_young;
- size_t _free_regions;
- size_t _regions_promoted_humongous;
- size_t _regions_promoted_regular;
- size_t _regular_promoted_garbage;
- size_t _regular_promoted_free;
- size_t _regions_immediate;
- size_t _immediate_size;
-
-public:
- ShenandoahEvacuationInformation() :
- _collection_set_regions(0), _collection_set_used_before(0), _collection_set_used_after(0),
- _collected_old(0), _collected_promoted(0), _collected_young(0), _free_regions(0),
- _regions_promoted_humongous(0), _regions_promoted_regular(0), _regular_promoted_garbage(0),
- _regular_promoted_free(0), _regions_immediate(0), _immediate_size(0) { }
-
- void set_collection_set_regions(size_t collection_set_regions) {
- _collection_set_regions = collection_set_regions;
- }
-
- void set_collection_set_used_before(size_t used) {
- _collection_set_used_before = used;
- }
-
- void set_collection_set_used_after(size_t used) {
- _collection_set_used_after = used;
- }
-
- void set_collected_old(size_t collected) {
- _collected_old = collected;
- }
-
- void set_collected_promoted(size_t collected) {
- _collected_promoted = collected;
- }
-
- void set_collected_young(size_t collected) {
- _collected_young = collected;
- }
-
- void set_free_regions(size_t freed) {
- _free_regions = freed;
- }
-
- void set_regions_promoted_humongous(size_t humongous) {
- _regions_promoted_humongous = humongous;
- }
-
- void set_regions_promoted_regular(size_t regular) {
- _regions_promoted_regular = regular;
- }
-
- void set_regular_promoted_garbage(size_t garbage) {
- _regular_promoted_garbage = garbage;
- }
-
- void set_regular_promoted_free(size_t free) {
- _regular_promoted_free = free;
- }
-
- void set_regions_immediate(size_t immediate) {
- _regions_immediate = immediate;
- }
-
- void set_immediate_size(size_t size) {
- _immediate_size = size;
- }
-
- size_t collection_set_regions() { return _collection_set_regions; }
- size_t collection_set_used_before() { return _collection_set_used_before; }
- size_t collection_set_used_after() { return _collection_set_used_after; }
- size_t collected_old() { return _collected_old; }
- size_t collected_promoted() { return _collected_promoted; }
- size_t collected_young() { return _collected_young; }
- size_t regions_promoted_humongous() { return _regions_promoted_humongous; }
- size_t regions_promoted_regular() { return _regions_promoted_regular; }
- size_t regular_promoted_garbage() { return _regular_promoted_garbage; }
- size_t regular_promoted_free() { return _regular_promoted_free; }
- size_t free_regions() { return _free_regions; }
- size_t regions_immediate() { return _regions_immediate; }
- size_t immediate_size() { return _immediate_size; }
-};
-
-#endif // SHARE_GC_SHENANDOAH_SHENANDOAHEVACINFO_HPP
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
index dd153718c9f..a786f8ae216 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
@@ -22,31 +22,31 @@
*
*/
-#include "gc/shenandoah/shenandoahEvacInfo.hpp"
+#include "gc/shenandoah/shenandoahCollectionSet.inline.hpp"
#include "gc/shenandoah/shenandoahTrace.hpp"
#include "jfr/jfrEvents.hpp"
-void ShenandoahTracer::report_evacuation_info(ShenandoahEvacuationInformation* info) {
- send_evacuation_info_event(info);
-}
+void ShenandoahTracer::report_evacuation_info(const ShenandoahCollectionSet* cset,
+ size_t free_regions, size_t regions_promoted_humongous, size_t regions_promoted_regular,
+ size_t regular_promoted_garbage, size_t regular_promoted_free, size_t regions_immediate,
+ size_t immediate_size) {
-void ShenandoahTracer::send_evacuation_info_event(ShenandoahEvacuationInformation* info) {
EventShenandoahEvacuationInformation e;
if (e.should_commit()) {
e.set_gcId(GCId::current());
- e.set_cSetRegions(info->collection_set_regions());
- e.set_cSetUsedBefore(info->collection_set_used_before());
- e.set_cSetUsedAfter(info->collection_set_used_after());
- e.set_collectedOld(info->collected_old());
- e.set_collectedPromoted(info->collected_promoted());
- e.set_collectedYoung(info->collected_young());
- e.set_regionsPromotedHumongous(info->regions_promoted_humongous());
- e.set_regionsPromotedRegular(info->regions_promoted_regular());
- e.set_regularPromotedGarbage(info->regular_promoted_garbage());
- e.set_regularPromotedFree(info->regular_promoted_free());
- e.set_freeRegions(info->free_regions());
- e.set_regionsImmediate(info->regions_immediate());
- e.set_immediateBytes(info->immediate_size());
+ e.set_cSetRegions(cset->count());
+ e.set_cSetUsedBefore(cset->used());
+ e.set_cSetUsedAfter(cset->live());
+ e.set_collectedOld(cset->get_old_bytes_reserved_for_evacuation());
+ e.set_collectedPromoted(cset->get_young_bytes_to_be_promoted());
+ e.set_collectedYoung(cset->get_young_bytes_reserved_for_evacuation());
+ e.set_regionsPromotedHumongous(regions_promoted_humongous);
+ e.set_regionsPromotedRegular(regions_promoted_regular);
+ e.set_regularPromotedGarbage(regular_promoted_garbage);
+ e.set_regularPromotedFree(regular_promoted_free);
+ e.set_freeRegions(free_regions);
+ e.set_regionsImmediate(regions_immediate);
+ e.set_immediateBytes(immediate_size);
e.commit();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
index a5351f4ef28..116968103de 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
@@ -28,15 +28,17 @@
#include "gc/shared/gcTrace.hpp"
#include "memory/allocation.hpp"
-class ShenandoahEvacuationInformation;
+class ShenandoahCollectionSet;
class ShenandoahTracer : public GCTracer, public CHeapObj {
public:
ShenandoahTracer() : GCTracer(Shenandoah) {}
- void report_evacuation_info(ShenandoahEvacuationInformation* info);
-private:
- void send_evacuation_info_event(ShenandoahEvacuationInformation* info);
+ // Sends a JFR event (if enabled) summarizing the composition of the collection set
+ static void report_evacuation_info(const ShenandoahCollectionSet* cset,
+ size_t free_regions, size_t regions_promoted_humongous, size_t regions_promoted_regular,
+ size_t regular_promoted_garbage, size_t regular_promoted_free, size_t regions_immediate,
+ size_t immediate_size);
};
#endif
From e4cb86df2b05cef6dd7e29e8803ebbbf5b4fe5a2 Mon Sep 17 00:00:00 2001
From: William Kemper
Date: Thu, 18 Sep 2025 18:53:08 +0000
Subject: [PATCH 042/664] 8367473: Shenandoah: Make the detailed evacuation
metrics a runtime diagnostic option 8367722: [GenShen]
ShenandoahEvacuationStats is always empty
Reviewed-by: ysr, phh
---
.../gc/shenandoah/shenandoahControlThread.cpp | 11 +++---
.../gc/shenandoah/shenandoahEvacTracker.cpp | 39 +++++++++++--------
.../shenandoah/shenandoahGenerationalHeap.cpp | 11 ++++--
.../share/gc/shenandoah/shenandoahHeap.cpp | 20 ++++++----
.../gc/shenandoah/shenandoah_globals.hpp | 7 ++++
5 files changed, 54 insertions(+), 34 deletions(-)
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index 80e5b709ada..f4005e45f39 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -211,12 +211,11 @@ void ShenandoahControlThread::run_service() {
ResourceMark rm;
LogStream ls(lt);
heap->phase_timings()->print_cycle_on(&ls);
-#ifdef NOT_PRODUCT
- ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker();
- ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
- evac_tracker->print_evacuations_on(&ls, &evac_stats.workers,
- &evac_stats.mutators);
-#endif
+ if (ShenandoahEvacTracking) {
+ ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker();
+ ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
+ evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, &evac_stats.mutators);
+ }
}
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
index 7883e2c5b29..bc8fad713af 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
@@ -108,8 +108,10 @@ void ShenandoahEvacuationStats::ShenandoahEvacuations::print_on(outputStream* st
void ShenandoahEvacuationStats::print_on(outputStream* st) const {
st->print("Young: "); _young.print_on(st);
- st->print("Promotion: "); _promotion.print_on(st);
- st->print("Old: "); _old.print_on(st);
+ if (ShenandoahHeap::heap()->mode()->is_generational()) {
+ st->print("Promotion: "); _promotion.print_on(st);
+ st->print("Old: "); _old.print_on(st);
+ }
if (_use_age_table) {
_age_table->print_on(st);
@@ -123,25 +125,28 @@ void ShenandoahEvacuationTracker::print_global_on(outputStream* st) {
void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st,
ShenandoahEvacuationStats* workers,
ShenandoahEvacuationStats* mutators) {
- st->print_cr("Workers: ");
- workers->print_on(st);
- st->cr();
- st->print_cr("Mutators: ");
- mutators->print_on(st);
- st->cr();
+ if (ShenandoahEvacTracking) {
+ st->print_cr("Workers: ");
+ workers->print_on(st);
+ st->cr();
+ st->print_cr("Mutators: ");
+ mutators->print_on(st);
+ st->cr();
+ }
ShenandoahHeap* heap = ShenandoahHeap::heap();
-
- AgeTable young_region_ages(false);
- for (uint i = 0; i < heap->num_regions(); ++i) {
- ShenandoahHeapRegion* r = heap->get_region(i);
- if (r->is_young()) {
- young_region_ages.add(r->age(), r->get_live_data_words());
+ if (heap->mode()->is_generational()) {
+ AgeTable young_region_ages(false);
+ for (uint i = 0; i < heap->num_regions(); ++i) {
+ ShenandoahHeapRegion* r = heap->get_region(i);
+ if (r->is_young()) {
+ young_region_ages.add(r->age(), r->get_live_data_words());
+ }
}
+ st->print("Young regions: ");
+ young_region_ages.print_on(st);
+ st->cr();
}
- st->print("Young regions: ");
- young_region_ages.print_on(st);
- st->cr();
}
class ShenandoahStatAggregator : public ThreadClosure {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
index e24109838a1..8a21ae376e1 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
@@ -324,8 +324,11 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
return ShenandoahBarrierSet::resolve_forwarded(p);
}
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
+
// Copy the object:
- NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
Copy::aligned_disjoint_words(cast_from_oop(p), copy, size);
oop copy_val = cast_to_oop(copy);
@@ -346,8 +349,10 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
// safe to do this on the public copy (this is also done during concurrent mark).
ContinuationGCSupport::relativize_stack_chunk(copy_val);
- // Record that the evacuation succeeded
- NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
+ if (ShenandoahEvacTracking) {
+ // Record that the evacuation succeeded
+ evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
if (target_gen == OLD_GENERATION) {
old_generation()->handle_evacuation(copy, size, from_region->is_young());
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index c2dca09a344..714c9cb9f5b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -1371,8 +1371,11 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
return ShenandoahBarrierSet::resolve_forwarded(p);
}
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
+
// Copy the object:
- NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
Copy::aligned_disjoint_words(cast_from_oop(p), copy, size);
// Try to install the new forwarding pointer.
@@ -1382,7 +1385,9 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
// Successfully evacuated. Our copy is now the public one!
ContinuationGCSupport::relativize_stack_chunk(copy_val);
shenandoah_assert_correct(nullptr, copy_val);
- NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
return copy_val;
} else {
// Failed to evacuate. We need to deal with the object that is left behind. Since this
@@ -1612,12 +1617,11 @@ void ShenandoahHeap::print_tracing_info() const {
ResourceMark rm;
LogStream ls(lt);
-#ifdef NOT_PRODUCT
- evac_tracker()->print_global_on(&ls);
-
- ls.cr();
- ls.cr();
-#endif
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->print_global_on(&ls);
+ ls.cr();
+ ls.cr();
+ }
phase_timings()->print_global_on(&ls);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
index c6a842c7754..d1531c51236 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
@@ -408,6 +408,13 @@
"events.") \
range(0,100) \
\
+ product(bool, ShenandoahEvacTracking, false, DIAGNOSTIC, \
+ "Collect additional metrics about evacuations. Enabling this " \
+ "tracks how many objects and how many bytes were evacuated, and " \
+ "how many were abandoned. The information will be categorized " \
+ "by thread type (worker or mutator) and evacuation type (young, " \
+ "old, or promotion.") \
+ \
product(uintx, ShenandoahMinYoungPercentage, 20, EXPERIMENTAL, \
"The minimum percentage of the heap to use for the young " \
"generation. Heuristics will not adjust the young generation " \
From 6e4e966d9b71ec04618e19784b5a661f34595ef6 Mon Sep 17 00:00:00 2001
From: William Kemper
Date: Thu, 18 Sep 2025 21:18:37 +0000
Subject: [PATCH 043/664] 8365792: GenShen: assertion "Generations aren't
reconciled"
Reviewed-by: xpeng, ysr
---
src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
index 93c218e9e8b..3d9fa10b0fc 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
@@ -543,7 +543,8 @@ void ShenandoahAsserts::assert_control_or_vm_thread_at_safepoint(bool at_safepoi
}
void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line) {
- if (!SafepointSynchronize::is_at_safepoint()) {
+ if (!ShenandoahSafepoint::is_at_shenandoah_safepoint()) {
+ // Only shenandoah safepoint operations participate in the active/gc generation scheme
return;
}
@@ -554,7 +555,7 @@ void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line
return;
}
- ShenandoahMessageBuffer msg("Active(%d) & GC(%d) Generations aren't reconciled", agen->type(), ggen->type());
+ ShenandoahMessageBuffer msg("Active(%s) & GC(%s) Generations aren't reconciled", agen->name(), ggen->name());
report_vm_error(file, line, msg.buffer());
}
From e3a4c28409ac62feee9efe069e3a3482e7e2cdd2 Mon Sep 17 00:00:00 2001
From: Ioi Lam
Date: Fri, 19 Sep 2025 01:04:28 +0000
Subject: [PATCH 044/664] 8362657: Make tables used in AOT assembly phase
GC-safe
Reviewed-by: shade, dholmes
---
src/hotspot/share/cds/aotMetaspace.cpp | 1 +
src/hotspot/share/cds/archiveHeapWriter.cpp | 22 +++++----
src/hotspot/share/cds/archiveHeapWriter.hpp | 3 +-
src/hotspot/share/cds/cdsHeapVerifier.cpp | 8 ++--
src/hotspot/share/cds/cdsHeapVerifier.hpp | 5 +-
src/hotspot/share/cds/heapShared.cpp | 51 +++++++++++++++++++--
src/hotspot/share/cds/heapShared.hpp | 20 ++++++--
7 files changed, 86 insertions(+), 24 deletions(-)
diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp
index 51227768293..f866461e7d4 100644
--- a/src/hotspot/share/cds/aotMetaspace.cpp
+++ b/src/hotspot/share/cds/aotMetaspace.cpp
@@ -720,6 +720,7 @@ void VM_PopulateDumpSharedSpace::doit() {
_map_info->set_cloned_vtables(CppVtables::vtables_serialized_base());
_map_info->header()->set_class_location_config(cl_config);
+ HeapShared::delete_tables_with_raw_oops();
CDSConfig::set_is_at_aot_safepoint(false);
}
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp
index c7750c70f1b..d1a8772874a 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -95,6 +95,11 @@ void ArchiveHeapWriter::init() {
}
}
+void ArchiveHeapWriter::delete_tables_with_raw_oops() {
+ delete _source_objs;
+ _source_objs = nullptr;
+}
+
void ArchiveHeapWriter::add_source_obj(oop src_obj) {
_source_objs->append(src_obj);
}
@@ -145,7 +150,7 @@ oop ArchiveHeapWriter::requested_obj_from_buffer_offset(size_t offset) {
oop ArchiveHeapWriter::source_obj_to_requested_obj(oop src_obj) {
assert(CDSConfig::is_dumping_heap(), "dump-time only");
- HeapShared::CachedOopInfo* p = HeapShared::archived_object_cache()->get(src_obj);
+ HeapShared::CachedOopInfo* p = HeapShared::get_cached_oop_info(src_obj);
if (p != nullptr) {
return requested_obj_from_buffer_offset(p->buffer_offset());
} else {
@@ -154,9 +159,9 @@ oop ArchiveHeapWriter::source_obj_to_requested_obj(oop src_obj) {
}
oop ArchiveHeapWriter::buffered_addr_to_source_obj(address buffered_addr) {
- oop* p = _buffer_offset_to_source_obj_table->get(buffered_address_to_offset(buffered_addr));
- if (p != nullptr) {
- return *p;
+ OopHandle* oh = _buffer_offset_to_source_obj_table->get(buffered_address_to_offset(buffered_addr));
+ if (oh != nullptr) {
+ return oh->resolve();
} else {
return nullptr;
}
@@ -356,12 +361,13 @@ void ArchiveHeapWriter::copy_source_objs_to_buffer(GrowableArrayCHeaplength(); i++) {
int src_obj_index = _source_objs_order->at(i)._index;
oop src_obj = _source_objs->at(src_obj_index);
- HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(src_obj);
+ HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(src_obj);
assert(info != nullptr, "must be");
size_t buffer_offset = copy_one_source_obj_to_buffer(src_obj);
info->set_buffer_offset(buffer_offset);
- _buffer_offset_to_source_obj_table->put_when_absent(buffer_offset, src_obj);
+ OopHandle handle(Universe::vm_global(), src_obj);
+ _buffer_offset_to_source_obj_table->put_when_absent(buffer_offset, handle);
_buffer_offset_to_source_obj_table->maybe_grow();
if (java_lang_Module::is_instance(src_obj)) {
@@ -696,7 +702,7 @@ void ArchiveHeapWriter::relocate_embedded_oops(GrowableArrayCHeaplength(); i++) {
int src_obj_index = _source_objs_order->at(i)._index;
oop src_obj = _source_objs->at(src_obj_index);
- HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(src_obj);
+ HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(src_obj);
assert(info != nullptr, "must be");
oop requested_obj = requested_obj_from_buffer_offset(info->buffer_offset());
update_header_for_requested_obj(requested_obj, src_obj, src_obj->klass());
@@ -758,7 +764,7 @@ void ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) {
NativePointerInfo info = _native_pointers->at(i);
oop src_obj = info._src_obj;
int field_offset = info._field_offset;
- HeapShared::CachedOopInfo* p = HeapShared::archived_object_cache()->get(src_obj);
+ HeapShared::CachedOopInfo* p = HeapShared::get_cached_oop_info(src_obj);
// requested_field_addr = the address of this field in the requested space
oop requested_obj = requested_obj_from_buffer_offset(p->buffer_offset());
Metadata** requested_field_addr = (Metadata**)(cast_from_oop(requested_obj) + field_offset);
diff --git a/src/hotspot/share/cds/archiveHeapWriter.hpp b/src/hotspot/share/cds/archiveHeapWriter.hpp
index 18e647912f1..80e72c12e7e 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.hpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.hpp
@@ -152,7 +152,7 @@ private:
};
static GrowableArrayCHeap* _source_objs_order;
- typedef ResizeableHashTable BufferOffsetToSourceObjectTable;
static BufferOffsetToSourceObjectTable* _buffer_offset_to_source_obj_table;
@@ -227,6 +227,7 @@ private:
public:
static void init() NOT_CDS_JAVA_HEAP_RETURN;
+ static void delete_tables_with_raw_oops();
static void add_source_obj(oop src_obj);
static bool is_too_large_to_archive(size_t size);
static bool is_too_large_to_archive(oop obj);
diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp
index a9f46c21ad3..9429a0d8264 100644
--- a/src/hotspot/share/cds/cdsHeapVerifier.cpp
+++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp
@@ -36,6 +36,7 @@
#include "oops/fieldStreams.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/oopHandle.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#if INCLUDE_CDS_JAVA_HEAP
@@ -273,7 +274,8 @@ void CDSHeapVerifier::add_static_obj_field(InstanceKlass* ik, oop field, Symbol*
// This function is called once for every archived heap object. Warn if this object is referenced by
// a static field of a class that's not aot-initialized.
-inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value) {
+inline bool CDSHeapVerifier::do_entry(OopHandle& orig_obj_handle, HeapShared::CachedOopInfo& value) {
+ oop orig_obj = orig_obj_handle.resolve();
_archived_objs++;
if (java_lang_String::is_instance(orig_obj) && HeapShared::is_dumped_interned_string(orig_obj)) {
@@ -323,7 +325,7 @@ public:
// Call this function (from gdb, etc) if you want to know why an object is archived.
void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) {
- HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(orig_obj);
+ HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(orig_obj);
if (info != nullptr) {
trace_to_root(st, orig_obj, nullptr, info);
} else {
@@ -357,7 +359,7 @@ const char* static_field_name(oop mirror, oop field) {
int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) {
int level = 0;
if (info->orig_referrer() != nullptr) {
- HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->orig_referrer());
+ HeapShared::CachedOopInfo* ref = HeapShared::get_cached_oop_info(info->orig_referrer());
assert(ref != nullptr, "sanity");
level = trace_to_root(st, info->orig_referrer(), orig_obj, ref) + 1;
} else if (java_lang_String::is_instance(orig_obj)) {
diff --git a/src/hotspot/share/cds/cdsHeapVerifier.hpp b/src/hotspot/share/cds/cdsHeapVerifier.hpp
index 811751e8ca2..1cc03975c5c 100644
--- a/src/hotspot/share/cds/cdsHeapVerifier.hpp
+++ b/src/hotspot/share/cds/cdsHeapVerifier.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include "cds/heapShared.hpp"
#include "memory/iterator.hpp"
+#include "oops/oopHandle.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
@@ -80,7 +81,7 @@ public:
virtual void do_klass(Klass* k);
// For HashTable::iterate()
- inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value);
+ inline bool do_entry(OopHandle& orig_obj, HeapShared::CachedOopInfo& value);
static void verify();
diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp
index 6b7cffdf321..92f55ce5b33 100644
--- a/src/hotspot/share/cds/heapShared.cpp
+++ b/src/hotspot/share/cds/heapShared.cpp
@@ -58,6 +58,7 @@
#include "oops/fieldStreams.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/oopHandle.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
@@ -159,12 +160,35 @@ bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) {
is_subgraph_root_class_of(fmg_archive_subgraph_entry_fields, ik);
}
+oop HeapShared::CachedOopInfo::orig_referrer() const {
+ return _orig_referrer.resolve();
+}
+
unsigned HeapShared::oop_hash(oop const& p) {
+ assert(SafepointSynchronize::is_at_safepoint() ||
+ JavaThread::current()->is_in_no_safepoint_scope(), "sanity");
// Do not call p->identity_hash() as that will update the
// object header.
return primitive_hash(cast_from_oop(p));
}
+unsigned int HeapShared::oop_handle_hash_raw(const OopHandle& oh) {
+ return oop_hash(oh.resolve());
+}
+
+unsigned int HeapShared::oop_handle_hash(const OopHandle& oh) {
+ oop o = oh.resolve();
+ if (o == nullptr) {
+ return 0;
+ } else {
+ return o->identity_hash();
+ }
+}
+
+bool HeapShared::oop_handle_equals(const OopHandle& a, const OopHandle& b) {
+ return a.resolve() == b.resolve();
+}
+
static void reset_states(oop obj, TRAPS) {
Handle h_obj(THREAD, obj);
InstanceKlass* klass = InstanceKlass::cast(obj->klass());
@@ -216,7 +240,8 @@ HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = nullptr;
bool HeapShared::has_been_archived(oop obj) {
assert(CDSConfig::is_dumping_heap(), "dump-time only");
- return archived_object_cache()->get(obj) != nullptr;
+ OopHandle oh(&obj);
+ return archived_object_cache()->get(oh) != nullptr;
}
int HeapShared::append_root(oop obj) {
@@ -303,7 +328,9 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra
count_allocation(obj->size());
ArchiveHeapWriter::add_source_obj(obj);
CachedOopInfo info = make_cached_oop_info(obj, referrer);
- archived_object_cache()->put_when_absent(obj, info);
+
+ OopHandle oh(Universe::vm_global(), obj);
+ archived_object_cache()->put_when_absent(oh, info);
archived_object_cache()->maybe_grow();
mark_native_pointers(obj);
@@ -636,14 +663,16 @@ void HeapShared::mark_native_pointers(oop orig_obj) {
}
void HeapShared::get_pointer_info(oop src_obj, bool& has_oop_pointers, bool& has_native_pointers) {
- CachedOopInfo* info = archived_object_cache()->get(src_obj);
+ OopHandle oh(&src_obj);
+ CachedOopInfo* info = archived_object_cache()->get(oh);
assert(info != nullptr, "must be");
has_oop_pointers = info->has_oop_pointers();
has_native_pointers = info->has_native_pointers();
}
void HeapShared::set_has_native_pointers(oop src_obj) {
- CachedOopInfo* info = archived_object_cache()->get(src_obj);
+ OopHandle oh(&src_obj);
+ CachedOopInfo* info = archived_object_cache()->get(oh);
assert(info != nullptr, "must be");
info->set_has_native_pointers();
}
@@ -1453,7 +1482,7 @@ public:
HeapShared::CachedOopInfo HeapShared::make_cached_oop_info(oop obj, oop referrer) {
PointsToOopsChecker points_to_oops_checker;
obj->oop_iterate(&points_to_oops_checker);
- return CachedOopInfo(referrer, points_to_oops_checker.result());
+ return CachedOopInfo(OopHandle(Universe::vm_global(), referrer), points_to_oops_checker.result());
}
void HeapShared::init_box_classes(TRAPS) {
@@ -2096,6 +2125,18 @@ bool HeapShared::is_dumped_interned_string(oop o) {
return _dumped_interned_strings->get(o) != nullptr;
}
+// These tables should be used only within the CDS safepoint, so
+// delete them before we exit the safepoint. Otherwise the table will
+// contain bad oops after a GC.
+void HeapShared::delete_tables_with_raw_oops() {
+ assert(_seen_objects_table == nullptr, "should have been deleted");
+
+ delete _dumped_interned_strings;
+ _dumped_interned_strings = nullptr;
+
+ ArchiveHeapWriter::delete_tables_with_raw_oops();
+}
+
void HeapShared::debug_trace() {
ResourceMark rm;
oop referrer = _object_being_archived.referrer();
diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp
index 110cdef8796..c9a810a6c0b 100644
--- a/src/hotspot/share/cds/heapShared.hpp
+++ b/src/hotspot/share/cds/heapShared.hpp
@@ -167,6 +167,9 @@ private:
public:
static void debug_trace();
static unsigned oop_hash(oop const& p);
+ static unsigned oop_handle_hash(OopHandle const& oh);
+ static unsigned oop_handle_hash_raw(OopHandle const& oh);
+ static bool oop_handle_equals(const OopHandle& a, const OopHandle& b);
static unsigned string_oop_hash(oop const& string) {
return java_lang_String::hash_code(string);
}
@@ -175,7 +178,7 @@ public:
class CachedOopInfo {
// Used by CDSHeapVerifier.
- oop _orig_referrer;
+ OopHandle _orig_referrer;
// The location of this object inside ArchiveHeapWriter::_buffer
size_t _buffer_offset;
@@ -186,12 +189,12 @@ public:
// One or more fields in this object are pointing to MetaspaceObj
bool _has_native_pointers;
public:
- CachedOopInfo(oop orig_referrer, bool has_oop_pointers)
+ CachedOopInfo(OopHandle orig_referrer, bool has_oop_pointers)
: _orig_referrer(orig_referrer),
_buffer_offset(0),
_has_oop_pointers(has_oop_pointers),
_has_native_pointers(false) {}
- oop orig_referrer() const { return _orig_referrer; }
+ oop orig_referrer() const;
void set_buffer_offset(size_t offset) { _buffer_offset = offset; }
size_t buffer_offset() const { return _buffer_offset; }
bool has_oop_pointers() const { return _has_oop_pointers; }
@@ -202,10 +205,11 @@ public:
private:
static const int INITIAL_TABLE_SIZE = 15889; // prime number
static const int MAX_TABLE_SIZE = 1000000;
- typedef ResizeableHashTable ArchivedObjectCache;
+ HeapShared::oop_handle_hash_raw,
+ HeapShared::oop_handle_equals> ArchivedObjectCache;
static ArchivedObjectCache* _archived_object_cache;
class DumpTimeKlassSubGraphInfoTable
@@ -378,6 +382,11 @@ private:
return _archived_object_cache;
}
+ static CachedOopInfo* get_cached_oop_info(oop orig_obj) {
+ OopHandle oh(&orig_obj);
+ return _archived_object_cache->get(oh);
+ }
+
static int archive_exception_instance(oop exception);
static bool archive_reachable_objects_from(int level,
@@ -435,6 +444,7 @@ private:
CDS_JAVA_HEAP_ONLY(return (idx == AOTMetaspace::hp);)
NOT_CDS_JAVA_HEAP_RETURN_(false);
}
+ static void delete_tables_with_raw_oops() NOT_CDS_JAVA_HEAP_RETURN;
static void resolve_classes(JavaThread* current) NOT_CDS_JAVA_HEAP_RETURN;
static void initialize_from_archived_subgraph(JavaThread* current, Klass* k) NOT_CDS_JAVA_HEAP_RETURN;
From 7ec3fa5f0a7408bf70e6226814d80dabd8a1a93c Mon Sep 17 00:00:00 2001
From: Jaikiran Pai
Date: Fri, 19 Sep 2025 01:36:41 +0000
Subject: [PATCH 045/664] 8367801: jtreg failure_handler - don't use the -L
option for ps command
Reviewed-by: ayang, shade
---
test/failure_handler/src/share/conf/linux.properties | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/failure_handler/src/share/conf/linux.properties b/test/failure_handler/src/share/conf/linux.properties
index 08e4ea8bd87..5cd625ce95a 100644
--- a/test/failure_handler/src/share/conf/linux.properties
+++ b/test/failure_handler/src/share/conf/linux.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2025, 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
@@ -108,7 +108,7 @@ system.sysctl.args=-a
process.top.app=top
process.top.args=-b -n 1
process.ps.app=ps
-process.ps.args=-Leo pid,pcpu,cputime,start,pmem,vsz,rssize,stackp,stat,sgi_p,wchan,user,args
+process.ps.args=-eo pid,pcpu,cputime,start,pmem,vsz,rssize,stackp,stat,sgi_p,wchan,user,args
memory.free.app=free
memory.free.args=-h
From c0815e40b6f5feeb4bfa791ccd91d662c205068d Mon Sep 17 00:00:00 2001
From: SendaoYan
Date: Fri, 19 Sep 2025 01:50:20 +0000
Subject: [PATCH 046/664] 8367904: Test java/net/InetAddress/ptr/Lookup.java
should throw SkippedException
Reviewed-by: fandreuzzi, dfuchs
---
test/jdk/java/net/InetAddress/ptr/Lookup.java | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/test/jdk/java/net/InetAddress/ptr/Lookup.java b/test/jdk/java/net/InetAddress/ptr/Lookup.java
index 1248916023e..39e5f720cef 100644
--- a/test/jdk/java/net/InetAddress/ptr/Lookup.java
+++ b/test/jdk/java/net/InetAddress/ptr/Lookup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@ import java.util.stream.Collectors;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
public class Lookup {
private static final String HOST = "icann.org";
@@ -91,8 +92,7 @@ public class Lookup {
String tmp = lookupWithIPv4Prefer();
System.out.println("IPv4 lookup results: [" + tmp + "]");
if (SKIP.equals(tmp)) {
- System.out.println(HOST + " can't be resolved - test skipped.");
- return;
+ throw new SkippedException(HOST + " can't be resolved - test skipped.");
}
String[] strs = tmp.split(":");
@@ -104,8 +104,7 @@ public class Lookup {
tmp = reverseWithIPv4Prefer(addr);
System.out.println("IPv4 reverse lookup results: [" + tmp + "]");
if (SKIP.equals(tmp)) {
- System.out.println(addr + " can't be resolved with preferIPv4 - test skipped.");
- return;
+ throw new SkippedException(addr + " can't be resolved with preferIPv4 - test skipped.");
}
strs = tmp.split(":");
From 5855fd2f654175c05341cc03ebf188d4db3e407d Mon Sep 17 00:00:00 2001
From: Prasanta Sadhukhan
Date: Fri, 19 Sep 2025 02:58:02 +0000
Subject: [PATCH 047/664] 8367784:
java/awt/Focus/InitialFocusTest/InitialFocusTest1.java failed with Wrong
focus owner
Reviewed-by: honkar, dnguyen
---
.../InitialFocusTest/InitialFocusTest1.java | 35 ++++++++++++-------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/test/jdk/java/awt/Focus/InitialFocusTest/InitialFocusTest1.java b/test/jdk/java/awt/Focus/InitialFocusTest/InitialFocusTest1.java
index 9edbcf8f71c..602a376655c 100644
--- a/test/jdk/java/awt/Focus/InitialFocusTest/InitialFocusTest1.java
+++ b/test/jdk/java/awt/Focus/InitialFocusTest/InitialFocusTest1.java
@@ -22,8 +22,10 @@
*/
import java.awt.Button;
+import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Frame;
+import java.awt.Robot;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
@@ -39,27 +41,36 @@ public class InitialFocusTest1 extends Frame implements FocusListener {
Button button1 = new Button("Button1");
Button button2 = new Button("Button2");
private static volatile Object focused;
+ private static InitialFocusTest1 app;
public static void main(final String[] args) throws Exception {
- InitialFocusTest1 app = new InitialFocusTest1();
try {
- app.setSize(200, 200);
- app.setLocationRelativeTo(null);
- app.setLayout(new FlowLayout());
+ Robot robot = new Robot();
+ EventQueue.invokeAndWait(() -> {
+ app = new InitialFocusTest1();
+ app.setLayout(new FlowLayout());
- app.button1.addFocusListener(app);
- app.button2.addFocusListener(app);
- app.add(app.button1);
- app.add(app.button2);
- app.setVisible(true);
- app.button2.requestFocus();
+ app.button1.addFocusListener(app);
+ app.button2.addFocusListener(app);
+ app.add(app.button1);
+ app.add(app.button2);
+
+ app.setSize(200, 200);
+ app.setLocationRelativeTo(null);
+ app.setVisible(true);
+ });
+ robot.waitForIdle();
+ robot.delay(1000);
+ EventQueue.invokeAndWait(() -> {
+ app.button2.requestFocus();
+ });
// wait for the very very last focus event
- Thread.sleep(10000);
+ robot.delay(1000);
if (app.button2 != focused) {
throw new RuntimeException("Wrong focus owner: " + focused);
}
} finally {
- app.dispose();
+ EventQueue.invokeAndWait(() -> app.dispose());
}
}
From 898fcff03745da29318e29ead189d78f8daa6988 Mon Sep 17 00:00:00 2001
From: Amit Kumar
Date: Fri, 19 Sep 2025 04:33:48 +0000
Subject: [PATCH 048/664] 8367325: [s390x] build failure due to JDK-8361376
Reviewed-by: mdoerr, dlong
---
.../gc/shared/barrierSetAssembler_s390.cpp | 1 +
.../gc/shared/barrierSetAssembler_s390.hpp | 8 +++++
.../s390/gc/shared/barrierSetNMethod_s390.cpp | 33 +++++++++++++------
3 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp
index 2d663061aec..c6f5a4e119c 100644
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp
@@ -171,6 +171,7 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re
void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
+ __ align(4, __ offset() + OFFSET_TO_PATCHABLE_DATA); // must align the following block which requires atomic updates
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
// Load jump addr:
diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp
index acc0d3b4988..3e0b2be4873 100644
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp
@@ -66,6 +66,14 @@ public:
OptoReg::Name refine_register(const Node* node,
OptoReg::Name opto_reg) const;
#endif // COMPILER2
+
+ static const int OFFSET_TO_PATCHABLE_DATA_INSTRUCTION = 6 + 6 + 6; // iihf(6) + iilf(6) + lg(6)
+ static const int BARRIER_TOTAL_LENGTH = OFFSET_TO_PATCHABLE_DATA_INSTRUCTION + 6 + 6 + 2; // cfi(6) + larl(6) + bcr(2)
+
+ // first 2 bytes are for cfi instruction opcode and next 4 bytes will be the value/data to be patched,
+ // so we are skipping first 2 bytes and returning the address of value/data field
+ static const int OFFSET_TO_PATCHABLE_DATA = 6 + 6 + 6 + 2; // iihf(6) + iilf(6) + lg(6) + CFI_OPCODE(2)
+
};
#ifdef COMPILER2
diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
index 8f43f4ef723..f6bf137da1c 100644
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
@@ -26,26 +26,32 @@
#include "code/codeBlob.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "utilities/debug.hpp"
class NativeMethodBarrier: public NativeInstruction {
private:
- static const int PATCHABLE_INSTRUCTION_OFFSET = 3*6; // bytes
address get_barrier_start_address() const {
return NativeInstruction::addr_at(0);
}
address get_patchable_data_address() const {
- address inst_addr = get_barrier_start_address() + PATCHABLE_INSTRUCTION_OFFSET;
+ address start_address = get_barrier_start_address();
+#ifdef ASSERT
+ address inst_addr = start_address + BarrierSetAssembler::OFFSET_TO_PATCHABLE_DATA_INSTRUCTION;
- DEBUG_ONLY(Assembler::is_z_cfi(*((long*)inst_addr)));
- return inst_addr + 2;
+ unsigned long instr = 0;
+ Assembler::get_instruction(inst_addr, &instr);
+ assert(Assembler::is_z_cfi(instr), "sanity check");
+#endif // ASSERT
+
+ return start_address + BarrierSetAssembler::OFFSET_TO_PATCHABLE_DATA;
}
public:
- static const int BARRIER_TOTAL_LENGTH = PATCHABLE_INSTRUCTION_OFFSET + 2*6 + 2; // bytes
+ static const int BARRIER_TOTAL_LENGTH = BarrierSetAssembler::BARRIER_TOTAL_LENGTH;
int get_guard_value() const {
address data_addr = get_patchable_data_address();
@@ -77,23 +83,30 @@ class NativeMethodBarrier: public NativeInstruction {
#ifdef ASSERT
void verify() const {
+ unsigned long instr = 0;
int offset = 0; // bytes
const address start = get_barrier_start_address();
- MacroAssembler::is_load_const(/* address */ start + offset); // two instructions
+ assert(MacroAssembler::is_load_const(/* address */ start + offset), "sanity check"); // two instructions
offset += Assembler::instr_len(&start[offset]);
offset += Assembler::instr_len(&start[offset]);
- Assembler::is_z_lg(*((long*)(start + offset)));
+ Assembler::get_instruction(start + offset, &instr);
+ assert(Assembler::is_z_lg(instr), "sanity check");
offset += Assembler::instr_len(&start[offset]);
- Assembler::is_z_cfi(*((long*)(start + offset)));
+ // it will be assignment operation, So it doesn't matter what value is already present in instr
+ // hence, no need to 0 it out.
+ Assembler::get_instruction(start + offset, &instr);
+ assert(Assembler::is_z_cfi(instr), "sanity check");
offset += Assembler::instr_len(&start[offset]);
- Assembler::is_z_larl(*((long*)(start + offset)));
+ Assembler::get_instruction(start + offset, &instr);
+ assert(Assembler::is_z_larl(instr), "sanity check");
offset += Assembler::instr_len(&start[offset]);
- Assembler::is_z_bcr(*((long*)(start + offset)));
+ Assembler::get_instruction(start + offset, &instr);
+ assert(Assembler::is_z_bcr(instr), "sanity check");
offset += Assembler::instr_len(&start[offset]);
assert(offset == BARRIER_TOTAL_LENGTH, "check offset == barrier length constant");
From 48d394a245e7d16423b3829efa326fe72605c8ee Mon Sep 17 00:00:00 2001
From: "Tagir F. Valeev"
Date: Fri, 19 Sep 2025 07:19:03 +0000
Subject: [PATCH 049/664] 8356995: Provide default methods min(T, T) and max(T,
T) in Comparator interface
Reviewed-by: rriggs, smarks
---
.../share/classes/java/util/Comparator.java | 49 +++++++++-
test/jdk/java/util/Comparator/MinMaxTest.java | 90 +++++++++++++++++++
2 files changed, 137 insertions(+), 2 deletions(-)
create mode 100644 test/jdk/java/util/Comparator/MinMaxTest.java
diff --git a/src/java.base/share/classes/java/util/Comparator.java b/src/java.base/share/classes/java/util/Comparator.java
index 6e0420d26e8..ad48dc94ed6 100644
--- a/src/java.base/share/classes/java/util/Comparator.java
+++ b/src/java.base/share/classes/java/util/Comparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@ import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
-import java.util.Comparators;
/**
* A comparison function, which imposes a total ordering on
@@ -189,6 +188,52 @@ public interface Comparator {
return Collections.reverseOrder(this);
}
+ /**
+ * Returns the greater of two values according to this comparator.
+ * If the arguments are equal with respect to this comparator,
+ * the {@code o1} argument is returned.
+ *
+ * @implSpec This default implementation behaves as if
+ * {@code compare(o1, o2) >= 0 ? o1 : o2}.
+ *
+ * @param o1 an argument.
+ * @param o2 another argument.
+ * @param the type of the arguments and the result.
+ * @return the larger of {@code o1} and {@code o2} according to this comparator.
+ * @throws NullPointerException if an argument is null and this
+ * comparator does not permit null arguments
+ * @throws ClassCastException if the arguments' types prevent them from
+ * being compared by this comparator.
+ *
+ * @since 26
+ */
+ default U max(U o1, U o2) {
+ return compare(o1, o2) >= 0 ? o1 : o2;
+ }
+
+ /**
+ * Returns the smaller of two values according to this comparator.
+ * If the arguments are equal with respect to this comparator,
+ * the {@code o1} argument is returned.
+ *
+ * @implSpec This default implementation behaves as if
+ * {@code compare(o1, o2) <= 0 ? o1 : o2}.
+ *
+ * @param o1 an argument.
+ * @param o2 another argument.
+ * @param the type of the arguments and the result.
+ * @return the smaller of {@code o1} and {@code o2} according to this comparator.
+ * @throws NullPointerException if an argument is null and this
+ * comparator does not permit null arguments
+ * @throws ClassCastException if the arguments' types prevent them from
+ * being compared by this comparator.
+ *
+ * @since 26
+ */
+ default U min(U o1, U o2) {
+ return compare(o1, o2) <= 0 ? o1 : o2;
+ }
+
/**
* Returns a lexicographic-order comparator with another comparator.
* If this {@code Comparator} considers two elements equal, i.e.
diff --git a/test/jdk/java/util/Comparator/MinMaxTest.java b/test/jdk/java/util/Comparator/MinMaxTest.java
new file mode 100644
index 00000000000..f1ef7d2d164
--- /dev/null
+++ b/test/jdk/java/util/Comparator/MinMaxTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8356995
+ * @summary Comparator min/max method tests
+ * @run junit MinMaxTest
+ */
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Comparator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class MinMaxTest {
+ @Test
+ void testMin() {
+ Comparator c = Comparator.naturalOrder();
+ assertEquals("a", c.min("a", "b"));
+ assertEquals("a", c.min("b", "a"));
+ }
+
+ @Test
+ void testMax() {
+ Comparator c = Comparator.naturalOrder();
+ assertEquals("b", c.max("a", "b"));
+ assertEquals("b", c.max("b", "a"));
+ }
+
+ @Test
+ void testThrowsNPE() {
+ Comparator c = Comparator.naturalOrder();
+ assertThrows(NullPointerException.class, () -> c.min(null, "a"));
+ assertThrows(NullPointerException.class, () -> c.min("a", null));
+ assertThrows(NullPointerException.class, () -> c.max(null, "a"));
+ assertThrows(NullPointerException.class, () -> c.max("a", null));
+ }
+
+ @Test
+ void testThrowsCCE() {
+ @SuppressWarnings("unchecked")
+ Comparator