diff --git a/.github/workflows/build-alpine-linux.yml b/.github/workflows/build-alpine-linux.yml
index 0d366a4bdd0..a39b342a248 100644
--- a/.github/workflows/build-alpine-linux.yml
+++ b/.github/workflows/build-alpine-linux.yml
@@ -59,7 +59,7 @@ on:
jobs:
build-linux:
name: build
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
container:
image: alpine:3.20
diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml
index b3c63f488a0..e70937f57b6 100644
--- a/.github/workflows/build-cross-compile.yml
+++ b/.github/workflows/build-cross-compile.yml
@@ -48,7 +48,7 @@ on:
jobs:
build-cross-compile:
name: build
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
strategy:
fail-fast: false
diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
index f398625cb2c..0680dea6bbe 100644
--- a/.github/workflows/build-linux.yml
+++ b/.github/workflows/build-linux.yml
@@ -75,7 +75,7 @@ on:
jobs:
build-linux:
name: build
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
strategy:
fail-fast: false
@@ -115,9 +115,21 @@ jobs:
if [[ '${{ inputs.apt-architecture }}' != '' ]]; then
sudo dpkg --add-architecture ${{ inputs.apt-architecture }}
fi
- sudo apt-get update
- sudo apt-get install --only-upgrade apt
- sudo apt-get install gcc-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} g++-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} libxrandr-dev${{ steps.arch.outputs.suffix }} libxtst-dev${{ steps.arch.outputs.suffix }} libcups2-dev${{ steps.arch.outputs.suffix }} libasound2-dev${{ steps.arch.outputs.suffix }} ${{ inputs.apt-extra-packages }}
+ sudo apt update
+ sudo apt install --only-upgrade apt
+ sudo apt install \
+ gcc-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} \
+ g++-${{ inputs.gcc-major-version }}${{ inputs.gcc-package-suffix }} \
+ libasound2-dev${{ steps.arch.outputs.suffix }} \
+ libcups2-dev${{ steps.arch.outputs.suffix }} \
+ libfontconfig1-dev${{ steps.arch.outputs.suffix }} \
+ libx11-dev${{ steps.arch.outputs.suffix }} \
+ libxext-dev${{ steps.arch.outputs.suffix }} \
+ libxrandr-dev${{ steps.arch.outputs.suffix }} \
+ libxrender-dev${{ steps.arch.outputs.suffix }} \
+ libxt-dev${{ steps.arch.outputs.suffix }} \
+ libxtst-dev${{ steps.arch.outputs.suffix }} \
+ ${{ inputs.apt-extra-packages }}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ inputs.gcc-major-version }} 100 --slave /usr/bin/g++ g++ /usr/bin/g++-${{ inputs.gcc-major-version }}
- name: 'Configure'
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 4d1e8a8be3d..09e6ed65a47 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -57,7 +57,7 @@ jobs:
prepare:
name: 'Prepare the run'
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
env:
# List of platforms to exclude by default
EXCLUDED_PLATFORMS: 'alpine-linux-x64'
@@ -405,7 +405,7 @@ jobs:
with:
platform: linux-x64
bootjdk-platform: linux-x64
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
debug-suffix: -debug
@@ -419,7 +419,7 @@ jobs:
with:
platform: linux-x64
bootjdk-platform: linux-x64
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
static-suffix: "-static"
diff --git a/.jcheck/conf b/.jcheck/conf
index 389dec7a448..27adc61e534 100644
--- a/.jcheck/conf
+++ b/.jcheck/conf
@@ -1,7 +1,7 @@
[general]
project=jdk-updates
jbs=JDK
-version=25.0.2
+version=25.0.3
[checks]
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists,copyright
diff --git a/README.md b/README.md
index b3f30676b3c..e5800fecd57 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,11 @@
-# Welcome to the JDK!
+# Welcome to OpenJDK 25 Updates!
+
+The JDK 25 Updates project uses two GitHub repositories.
+Updates are continuously developed in the repository [jdk25u-dev](https://github.com/openjdk/jdk25u-dev). This is the repository usually targeted by contributors.
+The [jdk25u](https://github.com/openjdk/jdk25u) repository is used for rampdown of the update releases of jdk25u and only accepts critical changes that must make the next release during rampdown. (You probably do not want to target jdk25u).
+
+For more OpenJDK 25 updates specific information such as timelines and contribution guidelines see the [project wiki page](https://wiki.openjdk.org/display/JDKUpdates/JDK+25u/).
+
For build instructions please see the
[online documentation](https://openjdk.org/groups/build/doc/building.html),
diff --git a/doc/building.html b/doc/building.html
index da8465bc532..51ced17fe99 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -668,7 +668,7 @@
Microsoft Visual Studio
(Note that this version is often presented as "MSVC 14.28", and reported
by cl.exe as 19.28.) Older versions will not be accepted by
configure and will not work. The maximum accepted version
-of Visual Studio is 2022.
+of Visual Studio is 2026.
If you have multiple versions of Visual Studio installed,
configure will by default pick the latest. You can request
a specific version to be used by setting
diff --git a/doc/building.md b/doc/building.md
index 1a9fe6b2e78..11af23d9447 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -468,7 +468,7 @@ available for this update.
The minimum accepted version is Visual Studio 2019 version 16.8. (Note that
this version is often presented as "MSVC 14.28", and reported by cl.exe as
19.28.) Older versions will not be accepted by `configure` and will not work.
-The maximum accepted version of Visual Studio is 2022.
+The maximum accepted version of Visual Studio is 2026.
If you have multiple versions of Visual Studio installed, `configure` will by
default pick the latest. You can request a specific version to be used by
diff --git a/make/autoconf/toolchain_microsoft.m4 b/make/autoconf/toolchain_microsoft.m4
index 17ad2666b3a..f577cf1a2a1 100644
--- a/make/autoconf/toolchain_microsoft.m4
+++ b/make/autoconf/toolchain_microsoft.m4
@@ -25,7 +25,7 @@
################################################################################
# The order of these defines the priority by which we try to find them.
-VALID_VS_VERSIONS="2022 2019"
+VALID_VS_VERSIONS="2022 2019 2026"
VS_DESCRIPTION_2019="Microsoft Visual Studio 2019"
VS_VERSION_INTERNAL_2019=142
@@ -57,6 +57,21 @@ VS_SDK_PLATFORM_NAME_2022=
VS_SUPPORTED_2022=true
VS_TOOLSET_SUPPORTED_2022=true
+VS_DESCRIPTION_2026="Microsoft Visual Studio 2026"
+VS_VERSION_INTERNAL_2026=145
+VS_MSVCR_2026=vcruntime140.dll
+VS_VCRUNTIME_1_2026=vcruntime140_1.dll
+VS_MSVCP_2026=msvcp140.dll
+VS_ENVVAR_2026="VS180COMNTOOLS"
+VS_USE_UCRT_2026="true"
+VS_VS_INSTALLDIR_2026="Microsoft Visual Studio/18"
+VS_EDITIONS_2026="BuildTools Community Professional Enterprise"
+VS_SDK_INSTALLDIR_2026=
+VS_VS_PLATFORM_NAME_2026="v145"
+VS_SDK_PLATFORM_NAME_2026=
+VS_SUPPORTED_2026=true
+VS_TOOLSET_SUPPORTED_2026=true
+
################################################################################
AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT],
diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk
index 03009ec3ca4..4868a9f12c0 100644
--- a/make/common/Utils.gmk
+++ b/make/common/Utils.gmk
@@ -78,7 +78,7 @@ EscapeDollar = $(subst $$,\$$,$(subst \$$,$$,$(strip $1)))
################################################################################
# This macro works just like EscapeDollar above, but for #.
-EscapeHash = $(subst \#,\\\#,$(subst \\\#,\#,$(strip $1)))
+EscapeHash = $(subst $(HASH),\$(HASH),$(subst \$(HASH),$(HASH),$(strip $1)))
################################################################################
# This macro translates $ into $$ to protect the string from make itself.
diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf
index ea97a2f2dd2..f82c7822485 100644
--- a/make/conf/version-numbers.conf
+++ b/make/conf/version-numbers.conf
@@ -28,15 +28,15 @@
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
-DEFAULT_VERSION_UPDATE=2
+DEFAULT_VERSION_UPDATE=3
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
-DEFAULT_VERSION_DATE=2026-01-20
+DEFAULT_VERSION_DATE=2026-04-21
DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25"
DEFAULT_JDK_SOURCE_TARGET_VERSION=25
-DEFAULT_PROMOTED_VERSION_PRE=
+DEFAULT_PROMOTED_VERSION_PRE=ea
diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk
index 6b5edc85b23..f7a7732993a 100644
--- a/make/hotspot/lib/CompileJvm.gmk
+++ b/make/hotspot/lib/CompileJvm.gmk
@@ -156,6 +156,10 @@ ifeq ($(call isTargetOs, windows), true)
WIN_EXPORT_FILE := $(JVM_OUTPUTDIR)/win-exports.def
endif
+ ifeq ($(SHIP_DEBUG_SYMBOLS), public)
+ CFLAGS_STRIPPED_DEBUGINFO := -DHAS_STRIPPED_DEBUGINFO
+ endif
+
JVM_LDFLAGS += -def:$(WIN_EXPORT_FILE)
endif
@@ -181,6 +185,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
CFLAGS := $(JVM_CFLAGS), \
abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
+ whitebox.cpp_CXXFLAGS := $(CFLAGS_STRIPPED_DEBUGINFO), \
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc), \
DISABLED_WARNINGS_gcc_ad_$(HOTSPOT_TARGET_CPU_ARCH).cpp := nonnull, \
DISABLED_WARNINGS_gcc_bytecodeInterpreter.cpp := unused-label, \
diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk
index a69b65180d7..5cb7501b6f4 100644
--- a/make/modules/java.desktop/lib/ClientLibraries.gmk
+++ b/make/modules/java.desktop/lib/ClientLibraries.gmk
@@ -236,7 +236,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
DISABLED_WARNINGS_gcc_dgif_lib.c := sign-compare, \
DISABLED_WARNINGS_gcc_jcmaster.c := implicit-fallthrough, \
DISABLED_WARNINGS_gcc_jdphuff.c := shift-negative-value, \
- DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized unused-function, \
+ DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized, \
DISABLED_WARNINGS_gcc_pngerror.c := maybe-uninitialized, \
DISABLED_WARNINGS_gcc_splashscreen_gfx_impl.c := implicit-fallthrough \
maybe-uninitialized, \
@@ -247,7 +247,6 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
DISABLED_WARNINGS_clang := deprecated-non-prototype, \
DISABLED_WARNINGS_clang_dgif_lib.c := sign-compare, \
DISABLED_WARNINGS_clang_gzwrite.c := format-nonliteral, \
- DISABLED_WARNINGS_clang_png.c := unused-function, \
DISABLED_WARNINGS_clang_splashscreen_impl.c := sign-compare \
unused-but-set-variable unused-function, \
DISABLED_WARNINGS_clang_splashscreen_png.c := \
diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
index a6aab24349a..b1b215a2170 100644
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
@@ -310,7 +310,18 @@ static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registe
__ add(sp, sp, 32 * wordSize);
}
+#ifdef R18_RESERVED
+ /*
+ Do not modify r18_tls when restoring registers if it is a reserved register. On Windows,
+ for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS
+ variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer.
+ */
+ __ pop(RegSet::range(r0, r17), sp);
+ __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize)));
+ __ pop(RegSet::range(r20, r29), sp);
+#else
__ pop(RegSet::range(r0, r29), sp);
+#endif
}
static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_fpu_registers = true) {
@@ -323,8 +334,20 @@ static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_f
__ add(sp, sp, 32 * wordSize);
}
+#ifdef R18_RESERVED
+ /*
+ Do not modify r18_tls when restoring registers if it is a reserved register. On Windows,
+ for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS
+ variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer.
+ */
+ __ ldp(zr, r1, Address(__ post(sp, 2 * wordSize)));
+ __ pop(RegSet::range(r2, r17), sp);
+ __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize)));
+ __ pop(RegSet::range(r20, r29), sp);
+#else
__ ldp(zr, r1, Address(__ post(sp, 16)));
__ pop(RegSet::range(r2, r29), sp);
+#endif
}
diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp
index 869e26d3359..302701e1cad 100644
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp
@@ -331,13 +331,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
__ ldr(rscratch2, thread_disarmed_and_epoch_addr);
__ cmp(rscratch1, rscratch2);
} else {
- assert(patching_type == NMethodPatchingType::conc_data_patch, "must be");
- // Subsequent loads of oops must occur after load of guard value.
- // BarrierSetNMethod::disarm sets guard with release semantics.
- __ membar(__ LoadLoad);
- Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()));
- __ ldrw(rscratch2, thread_disarmed_addr);
- __ cmpw(rscratch1, rscratch2);
+ ShouldNotReachHere();
}
__ br(condition, barrier_target);
diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp
index 0d6bfc98a72..fa093a6ef69 100644
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp
@@ -39,8 +39,7 @@ class Node;
enum class NMethodPatchingType {
stw_instruction_and_data_patch,
- conc_instruction_and_data_patch,
- conc_data_patch
+ conc_instruction_and_data_patch
};
class BarrierSetAssembler: public CHeapObj {
diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp
index c45611c882b..88c90a548d1 100644
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp
@@ -58,8 +58,6 @@ static int entry_barrier_offset(nmethod* nm) {
return -4 * (4 + slow_path_size(nm));
case NMethodPatchingType::conc_instruction_and_data_patch:
return -4 * (10 + slow_path_size(nm));
- case NMethodPatchingType::conc_data_patch:
- return -4 * (5 + slow_path_size(nm));
}
ShouldNotReachHere();
return 0;
diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp
index a12d4e2beec..c89847b9d52 100644
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp
@@ -67,7 +67,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
Register scratch, RegSet saved_regs);
public:
- virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
+ virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
diff --git a/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp b/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp
new file mode 100644
index 00000000000..579bfd3cb00
--- /dev/null
+++ b/src/hotspot/cpu/ppc/atomicAccess_ppc.hpp
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. 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 CPU_PPC_ATOMICACCESS_PPC_HPP
+#define CPU_PPC_ATOMICACCESS_PPC_HPP
+
+#ifndef PPC64
+#error "Atomic currently only implemented for PPC64"
+#endif
+
+#include "orderAccess_ppc.hpp"
+#include "utilities/debug.hpp"
+
+// Implementation of class AtomicAccess
+
+//
+// machine barrier instructions:
+//
+// - sync two-way memory barrier, aka fence
+// - lwsync orders Store|Store,
+// Load|Store,
+// Load|Load,
+// but not Store|Load
+// - eieio orders memory accesses for device memory (only)
+// - isync invalidates speculatively executed instructions
+// From the POWER ISA 2.06 documentation:
+// "[...] an isync instruction prevents the execution of
+// instructions following the isync until instructions
+// preceding the isync have completed, [...]"
+// From IBM's AIX assembler reference:
+// "The isync [...] instructions causes the processor to
+// refetch any instructions that might have been fetched
+// prior to the isync instruction. The instruction isync
+// causes the processor to wait for all previous instructions
+// to complete. Then any instructions already fetched are
+// discarded and instruction processing continues in the
+// environment established by the previous instructions."
+//
+// semantic barrier instructions:
+// (as defined in orderAccess.hpp)
+//
+// - release orders Store|Store, (maps to lwsync)
+// Load|Store
+// - acquire orders Load|Store, (maps to lwsync)
+// Load|Load
+// - fence orders Store|Store, (maps to sync)
+// Load|Store,
+// Load|Load,
+// Store|Load
+//
+
+inline void pre_membar(atomic_memory_order order) {
+ switch (order) {
+ case memory_order_relaxed:
+ case memory_order_acquire: break;
+ case memory_order_release:
+ case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break;
+ default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
+ }
+}
+
+inline void post_membar(atomic_memory_order order) {
+ switch (order) {
+ case memory_order_relaxed:
+ case memory_order_release: break;
+ case memory_order_acquire:
+ case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break;
+ default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
+ }
+}
+
+
+
+template
+struct Atomic::PlatformAdd {
+ template
+ D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
+
+ template
+ D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
+ return add_then_fetch(dest, add_value, order) - add_value;
+ }
+};
+
+template<>
+template
+inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(I));
+ STATIC_ASSERT(4 == sizeof(D));
+
+ D result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[dest] \n"
+ " add %[result], %[result], %[add_value] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [add_value] "r" (add_value),
+ [dest] "b" (dest)
+ : "cc", "memory" );
+
+ post_membar(order);
+
+ return result;
+}
+
+
+template<>
+template
+inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(I));
+ STATIC_ASSERT(8 == sizeof(D));
+
+ D result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[result], 0, %[dest] \n"
+ " add %[result], %[result], %[add_value] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [add_value] "r" (add_value),
+ [dest] "b" (dest)
+ : "cc", "memory" );
+
+ post_membar(order);
+
+ return result;
+}
+
+template<>
+template
+inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ // Note that xchg doesn't necessarily do an acquire
+ // (see synchronizer.cpp).
+
+ T old_value;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ /* atomic loop */
+ "1: \n"
+ " lwarx %[old_value], 0, %[dest] \n"
+ " stwcx. %[exchange_value], 0, %[dest] \n"
+ " bne- 1b \n"
+ /* exit */
+ "2: \n"
+ /* out */
+ : [old_value] "=&r" (old_value)
+ /* in */
+ : [dest] "b" (dest),
+ [exchange_value] "r" (exchange_value)
+ /* clobber */
+ : "cc",
+ "memory"
+ );
+
+ post_membar(order);
+
+ return old_value;
+}
+
+template<>
+template
+inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ // Note that xchg doesn't necessarily do an acquire
+ // (see synchronizer.cpp).
+
+ T old_value;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ /* atomic loop */
+ "1: \n"
+ " ldarx %[old_value], 0, %[dest] \n"
+ " stdcx. %[exchange_value], 0, %[dest] \n"
+ " bne- 1b \n"
+ /* exit */
+ "2: \n"
+ /* out */
+ : [old_value] "=&r" (old_value)
+ /* in */
+ : [dest] "b" (dest),
+ [exchange_value] "r" (exchange_value)
+ /* clobber */
+ : "cc",
+ "memory"
+ );
+
+ post_membar(order);
+
+ return old_value;
+}
+
+template<>
+template
+inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
+ T compare_value,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(1 == sizeof(T));
+
+ // Note that cmpxchg guarantees a two-way memory barrier across
+ // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
+ // specified otherwise (see atomicAccess.hpp).
+
+ const unsigned int masked_compare_val = (unsigned int)(unsigned char)compare_value;
+
+ unsigned int old_value;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ /* simple guard */
+ " lbz %[old_value], 0(%[dest]) \n"
+ " cmpw %[masked_compare_val], %[old_value] \n"
+ " bne- 2f \n"
+ /* atomic loop */
+ "1: \n"
+ " lbarx %[old_value], 0, %[dest] \n"
+ " cmpw %[masked_compare_val], %[old_value] \n"
+ " bne- 2f \n"
+ " stbcx. %[exchange_value], 0, %[dest] \n"
+ " bne- 1b \n"
+ /* exit */
+ "2: \n"
+ /* out */
+ : [old_value] "=&r" (old_value)
+ /* in */
+ : [dest] "b" (dest),
+ [masked_compare_val] "r" (masked_compare_val),
+ [exchange_value] "r" (exchange_value)
+ /* clobber */
+ : "cc",
+ "memory"
+ );
+
+ post_membar(order);
+
+ return PrimitiveConversions::cast((unsigned char)old_value);
+}
+
+template<>
+template
+inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
+ T compare_value,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+
+ // Note that cmpxchg guarantees a two-way memory barrier across
+ // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
+ // specified otherwise (see atomicAccess.hpp).
+
+ T old_value;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ /* simple guard */
+ " lwz %[old_value], 0(%[dest]) \n"
+ " cmpw %[compare_value], %[old_value] \n"
+ " bne- 2f \n"
+ /* atomic loop */
+ "1: \n"
+ " lwarx %[old_value], 0, %[dest] \n"
+ " cmpw %[compare_value], %[old_value] \n"
+ " bne- 2f \n"
+ " stwcx. %[exchange_value], 0, %[dest] \n"
+ " bne- 1b \n"
+ /* exit */
+ "2: \n"
+ /* out */
+ : [old_value] "=&r" (old_value)
+ /* in */
+ : [dest] "b" (dest),
+ [compare_value] "r" (compare_value),
+ [exchange_value] "r" (exchange_value)
+ /* clobber */
+ : "cc",
+ "memory"
+ );
+
+ post_membar(order);
+
+ return old_value;
+}
+
+template<>
+template
+inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
+ T compare_value,
+ T exchange_value,
+ atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+
+ // Note that cmpxchg guarantees a two-way memory barrier across
+ // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
+ // specified otherwise (see atomicAccess.hpp).
+
+ T old_value;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ /* simple guard */
+ " ld %[old_value], 0(%[dest]) \n"
+ " cmpd %[compare_value], %[old_value] \n"
+ " bne- 2f \n"
+ /* atomic loop */
+ "1: \n"
+ " ldarx %[old_value], 0, %[dest] \n"
+ " cmpd %[compare_value], %[old_value] \n"
+ " bne- 2f \n"
+ " stdcx. %[exchange_value], 0, %[dest] \n"
+ " bne- 1b \n"
+ /* exit */
+ "2: \n"
+ /* out */
+ : [old_value] "=&r" (old_value)
+ /* in */
+ : [dest] "b" (dest),
+ [compare_value] "r" (compare_value),
+ [exchange_value] "r" (exchange_value)
+ /* clobber */
+ : "cc",
+ "memory"
+ );
+
+ post_membar(order);
+
+ return old_value;
+}
+
+template
+struct Atomic::PlatformOrderedLoad
+{
+ template
+ T operator()(const volatile T* p) const {
+ T t = Atomic::load(p);
+ // Use twi-isync for load_acquire (faster than lwsync).
+ __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory");
+ return t;
+ }
+};
+
+template<>
+class Atomic::PlatformBitops<4, true> {
+public:
+ template
+ T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[old_value], 0, %[dest] \n"
+ " and %[result], %[old_value], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[old_value], 0, %[dest] \n"
+ " or %[result], %[old_value], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[old_value], 0, %[dest] \n"
+ " xor %[result], %[old_value], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[dest] \n"
+ " and %[result], %[result], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+
+ template
+ T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[dest] \n"
+ " or %[result], %[result], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+
+ template
+ T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(4 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[dest] \n"
+ " xor %[result], %[result], %[bits] \n"
+ " stwcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+};
+
+template<>
+class Atomic::PlatformBitops<8, true> {
+public:
+ template
+ T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[old_value], 0, %[dest] \n"
+ " and %[result], %[old_value], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[old_value], 0, %[dest] \n"
+ " or %[result], %[old_value], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T old_value, result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[old_value], 0, %[dest] \n"
+ " xor %[result], %[old_value], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [old_value] "=&r" (old_value),
+ [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return old_value;
+ }
+
+ template
+ T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[result], 0, %[dest] \n"
+ " and %[result], %[result], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+
+ template
+ T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[result], 0, %[dest] \n"
+ " or %[result], %[result], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+
+ template
+ T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
+ STATIC_ASSERT(8 == sizeof(T));
+ T result;
+
+ pre_membar(order);
+
+ __asm__ __volatile__ (
+ "1: ldarx %[result], 0, %[dest] \n"
+ " xor %[result], %[result], %[bits] \n"
+ " stdcx. %[result], 0, %[dest] \n"
+ " bne- 1b \n"
+ : [result] "=&r" (result)
+ : [dest] "b" (dest),
+ [bits] "r" (bits)
+ : "cc", "memory" );
+
+ post_membar(order);
+ return result;
+ }
+};
+#endif // CPU_PPC_ATOMICACCESS_PPC_HPP
diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp
index f48b1bc5f66..390623f48a1 100644
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp
@@ -40,8 +40,7 @@ class Node;
enum class NMethodPatchingType {
stw_instruction_and_data_patch,
- conc_instruction_and_data_patch,
- conc_data_patch
+ conc_instruction_and_data_patch
};
class BarrierSetAssembler: public CHeapObj {
diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp
index 6ee70b4b4ea..b058dcf1a2e 100644
--- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp
@@ -69,7 +69,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
Register preserve);
public:
- virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
+ virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
/* ==== C1 stubs ==== */
#ifdef COMPILER1
diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
index 0dd565048e1..4fa7b614aca 100644
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
@@ -1266,11 +1266,11 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
lhz(R11_scratch1, in_bytes(DataLayout::bci_offset()), R28_mdx);
ld(R12_scratch2, in_bytes(Method::const_offset()), R19_method);
addi(R11_scratch1, R11_scratch1, in_bytes(ConstMethod::codes_offset()));
- add(R11_scratch1, R12_scratch2, R12_scratch2);
+ add(R11_scratch1, R11_scratch1, R12_scratch2);
cmpd(CR0, R11_scratch1, R14_bcp);
beq(CR0, verify_continue);
- call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp ), R19_method, R14_bcp, R28_mdx);
+ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), R19_method, R14_bcp, R28_mdx);
bind(verify_continue);
#endif
diff --git a/src/hotspot/cpu/ppc/orderAccess_ppc.hpp b/src/hotspot/cpu/ppc/orderAccess_ppc.hpp
new file mode 100644
index 00000000000..f5fa8da755f
--- /dev/null
+++ b/src/hotspot/cpu/ppc/orderAccess_ppc.hpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. 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 CPU_PPC_ORDERACCESS_PPC_HPP
+#define CPU_PPC_ORDERACCESS_PPC_HPP
+
+#ifndef PPC64
+#error "OrderAccess currently only implemented for PPC64"
+#endif
+
+// Compiler version last used for testing: gcc 4.1.2
+// Please update this information when this file changes
+
+// Implementation of class OrderAccess.
+
+//
+// Machine barrier instructions:
+//
+// - sync Two-way memory barrier, aka fence.
+// - lwsync orders Store|Store,
+// Load|Store,
+// Load|Load,
+// but not Store|Load
+// - eieio orders Store|Store
+// - isync Invalidates speculatively executed instructions,
+// but isync may complete before storage accesses
+// associated with instructions preceding isync have
+// been performed.
+//
+// Semantic barrier instructions:
+// (as defined in orderAccess.hpp)
+//
+// - release orders Store|Store, (maps to lwsync)
+// Load|Store
+// - acquire orders Load|Store, (maps to lwsync)
+// Load|Load
+// - fence orders Store|Store, (maps to sync)
+// Load|Store,
+// Load|Load,
+// Store|Load
+//
+
+#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory");
+#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory");
+#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
+#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory");
+
+inline void OrderAccess::loadload() { inlasm_lwsync(); }
+inline void OrderAccess::storestore() { inlasm_lwsync(); }
+inline void OrderAccess::loadstore() { inlasm_lwsync(); }
+inline void OrderAccess::storeload() { inlasm_sync(); }
+
+inline void OrderAccess::acquire() { inlasm_lwsync(); }
+inline void OrderAccess::release() { inlasm_lwsync(); }
+inline void OrderAccess::fence() { inlasm_sync(); }
+inline void OrderAccess::cross_modify_fence_impl()
+ { inlasm_isync(); }
+
+#undef inlasm_sync
+#undef inlasm_lwsync
+#undef inlasm_eieio
+#undef inlasm_isync
+
+#endif // CPU_PPC_ORDERACCESS_PPC_HPP
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index 128e566d0f3..a04e397c52b 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -12583,27 +12583,27 @@ instruct countTrailingZerosL_cnttzd(iRegIdst dst, iRegLsrc src) %{
%}
// Expand nodes for byte_reverse_int.
-instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{
- effect(DEF dst, USE src, USE pos, USE shift);
+instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{
+ effect(DEF dst, USE src, USE n, USE b);
predicate(false);
- format %{ "INSRWI $dst, $src, $pos, $shift" %}
+ format %{ "INSRWI $dst, $src, $n, $b" %}
size(4);
ins_encode %{
- __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant);
+ __ insrwi($dst$$Register, $src$$Register, $n$$constant, $b$$constant);
%}
ins_pipe(pipe_class_default);
%}
// As insrwi_a, but with USE_DEF.
-instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{
- effect(USE_DEF dst, USE src, USE pos, USE shift);
+instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{
+ effect(USE_DEF dst, USE src, USE n, USE b);
predicate(false);
- format %{ "INSRWI $dst, $src, $pos, $shift" %}
+ format %{ "INSRWI $dst, $src, $n, $b" %}
size(4);
ins_encode %{
- __ insrwi($dst$$Register, $src$$Register, $shift$$constant, $pos$$constant);
+ __ insrwi($dst$$Register, $src$$Register, $n$$constant, $b$$constant);
%}
ins_pipe(pipe_class_default);
%}
@@ -12625,12 +12625,12 @@ instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{
iRegLdst tmpI3;
urShiftI_reg_imm(tmpI1, src, imm24);
- insrwi_a(dst, tmpI1, imm24, imm8);
+ insrwi_a(dst, tmpI1, imm8, imm24);
urShiftI_reg_imm(tmpI2, src, imm16);
- insrwi(dst, tmpI2, imm8, imm16);
+ insrwi(dst, tmpI2, imm16, imm8);
urShiftI_reg_imm(tmpI3, src, imm8);
insrwi(dst, tmpI3, imm8, imm8);
- insrwi(dst, src, imm0, imm8);
+ insrwi(dst, src, imm8, imm0);
%}
%}
@@ -12748,7 +12748,7 @@ instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{
immI16 imm8 %{ (int) 8 %}
urShiftI_reg_imm(dst, src, imm8);
- insrwi(dst, src, imm16, imm8);
+ insrwi(dst, src, imm8, imm16);
%}
%}
@@ -12777,7 +12777,7 @@ instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{
iRegLdst tmpI1;
urShiftI_reg_imm(tmpI1, src, imm8);
- insrwi(tmpI1, src, imm16, imm8);
+ insrwi(tmpI1, src, imm8, imm16);
extsh(dst, tmpI1);
%}
%}
diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
index ee65050ffae..721364ce412 100644
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
@@ -109,6 +109,10 @@ void VM_Version::initialize() {
}
MaxVectorSize = SuperwordUseVSX ? 16 : 8;
+ if (!SuperwordUseVSX && FLAG_IS_DEFAULT(EnableVectorSupport)) {
+ // VectorSupport intrinsics currently have issues with MaxVectorSize < 16 (JDK-8370803).
+ FLAG_SET_ERGO(EnableVectorSupport, false);
+ }
if (FLAG_IS_DEFAULT(AlignVector)) {
FLAG_SET_ERGO(AlignVector, false);
}
diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
index 7e9bea381a5..387db778c1f 100644
--- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
@@ -241,10 +241,6 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
__ lwu(t0, *guard);
switch (patching_type) {
- case NMethodPatchingType::conc_data_patch:
- // Subsequent loads of oops must occur after load of guard value.
- // BarrierSetNMethod::disarm sets guard with release semantics.
- __ membar(MacroAssembler::LoadLoad); // fall through to stw_instruction_and_data_patch
case NMethodPatchingType::stw_instruction_and_data_patch:
{
// With STW patching, no data or instructions are updated concurrently,
diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp
index 7061dca738c..63a7032bb84 100644
--- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp
@@ -40,8 +40,7 @@ class Node;
enum class NMethodPatchingType {
stw_instruction_and_data_patch,
- conc_instruction_and_data_patch,
- conc_data_patch
+ conc_instruction_and_data_patch
};
class BarrierSetAssembler: public CHeapObj {
diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp
index f24e4f789bc..ac619f83f7d 100644
--- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp
@@ -50,8 +50,6 @@ static int entry_barrier_offset(nmethod* nm) {
switch (bs_asm->nmethod_patching_type()) {
case NMethodPatchingType::stw_instruction_and_data_patch:
return -4 * (4 + slow_path_size(nm));
- case NMethodPatchingType::conc_data_patch:
- return -4 * (5 + slow_path_size(nm));
case NMethodPatchingType::conc_instruction_and_data_patch:
return -4 * (15 + slow_path_size(nm));
}
diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp
index 7d12cc8cbb6..3fe7c8d1740 100644
--- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp
@@ -69,7 +69,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
public:
- virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
+ virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; }
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp
index 39b6737631d..d770999df96 100644
--- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp
+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp
@@ -93,14 +93,60 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) {}
+void MethodHandles::verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) {
+ BLOCK_COMMENT("verify_method {");
+ __ verify_method_ptr(method);
+ if (VerifyMethodHandles) {
+ Label L_ok;
+ assert_different_registers(method, t0, t1);
+ const Register method_holder = t1;
+ __ load_method_holder(method_holder, method);
+
+ switch (iid) {
+ case vmIntrinsicID::_invokeBasic:
+ // Require compiled LambdaForm class to be fully initialized.
+ __ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset()));
+ __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
+ __ mv(t1, InstanceKlass::fully_initialized);
+ __ beq(t0, t1, L_ok);
+ break;
+ case vmIntrinsicID::_linkToStatic:
+ __ clinit_barrier(method_holder, t0, &L_ok);
+ break;
+
+ case vmIntrinsicID::_linkToVirtual:
+ case vmIntrinsicID::_linkToSpecial:
+ case vmIntrinsicID::_linkToInterface:
+ // Class initialization check is too strong here. Just ensure that class initialization has been initiated.
+ __ lbu(t0, Address(method_holder, InstanceKlass::init_state_offset()));
+ __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
+ __ mv(t1, InstanceKlass::being_initialized);
+ __ bge(t0, t1, L_ok);
+
+ // init_state check failed, but it may be an abstract interface method
+ __ lhu(t0, Address(method, Method::access_flags_offset()));
+ __ test_bit(t1, t0, exact_log2(JVM_ACC_ABSTRACT));
+ __ bnez(t1, L_ok);
+ break;
+
+ default:
+ fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid));
+ }
+
+ // Method holder init state check failed for a concrete method.
+ __ stop("Method holder klass is not initialized");
+ __ BIND(L_ok);
+ }
+ BLOCK_COMMENT("} verify_method");
+}
#endif //ASSERT
void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp,
- bool for_compiler_entry) {
+ bool for_compiler_entry, vmIntrinsics::ID iid) {
assert(method == xmethod, "interpreter calling convention");
Label L_no_such_method;
__ beqz(xmethod, L_no_such_method);
- __ verify_method_ptr(method);
+ verify_method(_masm, method, iid);
if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code;
@@ -158,7 +204,7 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
__ BIND(L);
}
- jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry);
+ jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry, vmIntrinsics::_invokeBasic);
BLOCK_COMMENT("} jump_to_lambda_form");
}
@@ -437,8 +483,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
// After figuring out which concrete method to call, jump into it.
// Note that this works in the interpreter with no data motion.
// But the compiled version will require that r2_recv be shifted out.
- __ verify_method_ptr(xmethod);
- jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry);
+ jump_from_method_handle(_masm, xmethod, temp1, for_compiler_entry, iid);
if (iid == vmIntrinsics::_linkToInterface) {
__ bind(L_incompatible_class_change_error);
__ far_jump(RuntimeAddress(SharedRuntime::throw_IncompatibleClassChangeError_entry()));
diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp
index 6017b26c66d..ffc3b3ab676 100644
--- a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp
+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp
@@ -39,6 +39,8 @@ enum /* platform_dependent_constants */ {
Register obj, vmClassID klass_id,
const char* error_message = "wrong klass") NOT_DEBUG_RETURN;
+ static void verify_method(MacroAssembler* _masm, Register method, vmIntrinsics::ID iid) NOT_DEBUG_RETURN;
+
static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) {
verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle),
"reference is a MH");
@@ -49,7 +51,7 @@ enum /* platform_dependent_constants */ {
// Similar to InterpreterMacroAssembler::jump_from_interpreted.
// Takes care of special dispatch from single stepping too.
static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp,
- bool for_compiler_entry);
+ bool for_compiler_entry, vmIntrinsics::ID iid);
static void jump_to_lambda_form(MacroAssembler* _masm,
Register recv, Register method_temp,
diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
index 9079c2d6c1f..50076d7c8ce 100644
--- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp
@@ -274,19 +274,6 @@ void NativeMovConstReg::print() {
p2i(instruction_address()), data());
}
-//-------------------------------------------------------------------
-
-int NativeMovRegMem::offset() const {
- Unimplemented();
- return 0;
-}
-
-void NativeMovRegMem::set_offset(int x) { Unimplemented(); }
-
-void NativeMovRegMem::verify() {
- Unimplemented();
-}
-
//--------------------------------------------------------------------------------
void NativeJump::verify() { }
diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
index b718b840e02..a50f14d7923 100644
--- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
@@ -37,7 +37,7 @@
// - NativeInstruction
// - - NativeCall
// - - NativeMovConstReg
-// - - NativeMovRegMem
+// - - NativeMovRegMem - Unimplemented
// - - NativeJump
// - - NativeGeneralJump
// - - NativeIllegalInstruction
@@ -233,38 +233,18 @@ inline NativeMovConstReg* nativeMovConstReg_before(address addr) {
// NativeMovRegMem to keep some compilers happy.
class NativeMovRegMem: public NativeInstruction {
public:
- enum RISCV_specific_constants {
- instruction_size = NativeInstruction::instruction_size,
- instruction_offset = 0,
- data_offset = 0,
- next_instruction_offset = NativeInstruction::instruction_size
- };
-
- int instruction_start() const { return instruction_offset; }
-
- address instruction_address() const { return addr_at(instruction_offset); }
-
- int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; }
+ int num_bytes_to_end_of_patch() const { Unimplemented(); return 0; }
- int offset() const;
+ int offset() const { Unimplemented(); return 0; }
- void set_offset(int x);
+ void set_offset(int x) { Unimplemented(); }
- void add_offset_in_bytes(int add_offset) {
- set_offset(offset() + add_offset);
- }
-
- void verify();
- void print();
-
- private:
- inline friend NativeMovRegMem* nativeMovRegMem_at(address addr);
+ void add_offset_in_bytes(int add_offset) { Unimplemented(); }
};
inline NativeMovRegMem* nativeMovRegMem_at(address addr) {
- NativeMovRegMem* test = (NativeMovRegMem*)(addr - NativeMovRegMem::instruction_offset);
- DEBUG_ONLY(test->verify());
- return test;
+ Unimplemented();
+ return (NativeMovRegMem*)nullptr;
}
class NativeJump: public NativeInstruction {
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index eff4cfb61e8..9b7e7138710 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -1184,6 +1184,8 @@ bool is_CAS(int opcode, bool maybe_volatile)
}
}
+constexpr uint64_t MAJIK_DWORD = 0xabbaabbaabbaabbaull;
+
// predicate controlling translation of CAS
//
// returns true if CAS needs to use an acquiring load otherwise false
@@ -1363,10 +1365,15 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print("# stack bang size=%d\n\t", framesize);
}
- st->print("sd fp, [sp, #%d]\n\t", - 2 * wordSize);
- st->print("sd ra, [sp, #%d]\n\t", - wordSize);
- if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); }
st->print("sub sp, sp, #%d\n\t", framesize);
+ st->print("sd fp, [sp, #%d]\n\t", framesize - 2 * wordSize);
+ st->print("sd ra, [sp, #%d]\n\t", framesize - wordSize);
+ if (PreserveFramePointer) { st->print("add fp, sp, #%d\n\t", framesize); }
+
+ if (VerifyStackAtCalls) {
+ st->print("mv t2, %ld\n\t", MAJIK_DWORD);
+ st->print("sd t2, [sp, #%d]\n\t", framesize - 3 * wordSize);
+ }
if (C->stub_function() == nullptr) {
st->print("ld t0, [guard]\n\t");
@@ -1416,6 +1423,11 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
__ build_frame(framesize);
+ if (VerifyStackAtCalls) {
+ __ mv(t2, MAJIK_DWORD);
+ __ sd(t2, Address(sp, framesize - 3 * wordSize));
+ }
+
if (C->stub_function() == nullptr) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
// Dummy labels for just measuring the code size
@@ -1437,10 +1449,6 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
bs->nmethod_entry_barrier(masm, slow_path, continuation, guard);
}
- if (VerifyStackAtCalls) {
- Unimplemented();
- }
-
C->output()->set_frame_complete(__ offset());
if (C->has_mach_constant_base_node()) {
@@ -2430,7 +2438,13 @@ encode %{
enc_class riscv_enc_call_epilog() %{
if (VerifyStackAtCalls) {
// Check that stack depth is unchanged: find majik cookie on stack
- __ call_Unimplemented();
+ int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3 * VMRegImpl::slots_per_word));
+ Label stack_ok;
+ __ ld(t1, Address(sp, framesize));
+ __ mv(t2, MAJIK_DWORD);
+ __ beq(t2, t1, stack_ok);
+ __ stop("MAJIK_DWORD not found");
+ __ bind(stack_ok);
}
%}
@@ -8541,7 +8555,7 @@ instruct convD2F_reg(fRegF dst, fRegD src) %{
// single <-> half precision
-instruct convHF2F_reg_reg(fRegF dst, iRegINoSp src, iRegINoSp tmp) %{
+instruct convHF2F_reg_reg(fRegF dst, iRegIorL2I src, iRegINoSp tmp) %{
match(Set dst (ConvHF2F src));
effect(TEMP tmp);
format %{ "fmv.h.x $dst, $src\t# move source from $src to $dst\n\t"
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index f2845ee2a6c..a824f33367c 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -114,12 +114,12 @@ source %{
case Op_VectorCastHF2F:
case Op_VectorCastF2HF:
case Op_AddVHF:
+ case Op_SubVHF:
+ case Op_MulVHF:
case Op_DivVHF:
case Op_MaxVHF:
case Op_MinVHF:
- case Op_MulVHF:
case Op_SqrtVHF:
- case Op_SubVHF:
return UseZvfh;
case Op_FmaVHF:
return UseZvfh && UseFMA;
@@ -147,13 +147,28 @@ source %{
if (!UseRVV) {
return false;
}
+
switch (opcode) {
case Op_SelectFromTwoVector:
// There is no masked version of selectFrom two vector, i.e. selectFrom(av, bv, mask) in vector API.
return false;
+ // Currently, the masked versions of the following 8 Float16 operations are disabled.
+ // When the support for Float16 vector classes is added in VectorAPI and the masked
+ // Float16 IR can be generated, these masked operations will be enabled and relevant
+ // backend support added.
+ case Op_AddVHF:
+ case Op_SubVHF:
+ case Op_MulVHF:
+ case Op_DivVHF:
+ case Op_MaxVHF:
+ case Op_MinVHF:
+ case Op_SqrtVHF:
+ case Op_FmaVHF:
+ return false;
default:
break;
}
+
return match_rule_supported_vector(opcode, vlen, bt);
}
diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
index 759772b717d..3b2d7977b7c 100644
--- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
@@ -213,7 +213,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
// Is vector's size (in bytes) bigger than a size saved by default?
// riscv does not ovlerlay the floating-point registers on vector registers like aarch64.
bool SharedRuntime::is_wide_vector(int size) {
- return UseRVV;
+ return UseRVV && size > 0;
}
// ---------------------------------------------------------------------------
@@ -2486,7 +2486,7 @@ void SharedRuntime::generate_deopt_blob() {
// EPILOG must remove this many slots.
// RISCV needs two words for RA (return address) and FP (frame pointer).
uint SharedRuntime::in_preserve_stack_slots() {
- return 2 * VMRegImpl::slots_per_word;
+ return 2 * VMRegImpl::slots_per_word + (VerifyStackAtCalls ? 0 : 2) ;
}
uint SharedRuntime::out_preserve_stack_slots() {
diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
index 21164107053..a478cd7b183 100644
--- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
@@ -1148,9 +1148,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
Label L;
__ ld(x28, Address(xmethod, Method::native_function_offset()));
ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry());
- __ la(t, unsatisfied);
- __ load_long_misaligned(t1, Address(t, 0), t0, 2); // 2 bytes aligned, but not 4 or 8
-
+ __ la(t1, unsatisfied);
__ bne(x28, t1, L);
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
index 627a5cec243..2c4ea70b9f8 100644
--- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
@@ -708,7 +708,6 @@ void TemplateTable::index_check(Register array, Register index) {
__ mv(x11, index);
}
Label ok;
- __ sext(index, index, 32);
__ bltu(index, length, ok);
__ mv(x13, array);
__ mv(t1, Interpreter::_throw_ArrayIndexOutOfBoundsException_entry);
@@ -1052,7 +1051,7 @@ void TemplateTable::aastore() {
transition(vtos, vtos);
// stack: ..., array, index, value
__ ld(x10, at_tos()); // value
- __ ld(x12, at_tos_p1()); // index
+ __ lw(x12, at_tos_p1()); // index
__ ld(x13, at_tos_p2()); // array
index_check(x13, x12); // kills x11
@@ -1462,9 +1461,9 @@ void TemplateTable::iinc() {
transition(vtos, vtos);
__ load_signed_byte(x11, at_bcp(2)); // get constant
locals_index(x12);
- __ ld(x10, iaddress(x12, x10, _masm));
+ __ lw(x10, iaddress(x12, x10, _masm));
__ addw(x10, x10, x11);
- __ sd(x10, iaddress(x12, t0, _masm));
+ __ sw(x10, iaddress(x12, t0, _masm));
}
void TemplateTable::wide_iinc() {
@@ -1477,9 +1476,9 @@ void TemplateTable::wide_iinc() {
__ orr(x11, x11, t1);
locals_index_wide(x12);
- __ ld(x10, iaddress(x12, t0, _masm));
+ __ lw(x10, iaddress(x12, t0, _masm));
__ addw(x10, x10, x11);
- __ sd(x10, iaddress(x12, t0, _masm));
+ __ sw(x10, iaddress(x12, t0, _masm));
}
void TemplateTable::convert() {
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
index 9a44609ba55..fb04c272385 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
@@ -165,11 +165,6 @@ void VM_Version::common_initialize() {
(unaligned_scalar.value() == MISALIGNED_SCALAR_FAST));
}
- if (FLAG_IS_DEFAULT(AlignVector)) {
- FLAG_SET_DEFAULT(AlignVector,
- unaligned_vector.value() != MISALIGNED_VECTOR_FAST);
- }
-
#ifdef __riscv_ztso
// Hotspot is compiled with TSO support, it will only run on hardware which
// supports Ztso
@@ -270,6 +265,11 @@ void VM_Version::c2_initialize() {
}
}
+ if (FLAG_IS_DEFAULT(AlignVector)) {
+ FLAG_SET_DEFAULT(AlignVector,
+ unaligned_vector.value() != MISALIGNED_VECTOR_FAST);
+ }
+
// NOTE: Make sure codes dependent on UseRVV are put after MaxVectorSize initialize,
// as there are extra checks inside it which could disable UseRVV
// in some situations.
diff --git a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp
index ee2d6d8a0be..962f7866259 100644
--- a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp
+++ b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -1330,10 +1330,12 @@ static void big_case_loop_helper(bool sizeKnown, int size, Label &noMatch, Label
// Clarification: The BYTE_K compare above compares haystack[(n-32):(n-1)]. We need to
// compare haystack[(k-1):(k-1+31)]. Subtracting either index gives shift value of
// (k + 31 - n): x = (k-1+31)-(n-1) = k-1+31-n+1 = k+31-n.
+ // When isU is set, similarly, shift is from haystack[(n-32):(n-1)] to [(k-2):(k-2+31)]
+
if (sizeKnown) {
- __ movl(temp2, 31 + size);
+ __ movl(temp2, (isU ? 30 : 31) + size);
} else {
- __ movl(temp2, 31);
+ __ movl(temp2, isU ? 30 : 31);
__ addl(temp2, needleLen);
}
__ subl(temp2, hsLength);
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp
index b02dd295776..aa523cba524 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp
@@ -3524,10 +3524,10 @@ void StubGenerator::aesgcm_avx512(Register in, Register len, Register ct, Regist
false, true, false, false, false, ghashin_offset, aesout_offset, HashKey_32);
ghash16_avx512(false, true, false, false, true, in, pos, avx512_subkeyHtbl, AAD_HASHx, SHUF_MASK, stack_offset, 16 * 16, 0, HashKey_16);
+ __ addl(pos, 16 * 16);
__ bind(MESG_BELOW_32_BLKS);
__ subl(len, 16 * 16);
- __ addl(pos, 16 * 16);
gcm_enc_dec_last_avx512(len, in, pos, AAD_HASHx, SHUF_MASK, avx512_subkeyHtbl, ghashin_offset, HashKey_16, true, true);
__ bind(GHASH_DONE);
@@ -4016,13 +4016,15 @@ void StubGenerator::aesgcm_avx2(Register in, Register len, Register ct, Register
const Register rounds = r10;
const XMMRegister ctr_blockx = xmm9;
const XMMRegister aad_hashx = xmm8;
- Label encrypt_done, encrypt_by_8_new, encrypt_by_8;
+ Label encrypt_done, encrypt_by_8_new, encrypt_by_8, exit;
//This routine should be called only for message sizes of 128 bytes or more.
//Macro flow:
//process 8 16 byte blocks in initial_num_blocks.
//process 8 16 byte blocks at a time until all are done 'encrypt_by_8_new followed by ghash_last_8'
__ xorl(pos, pos);
+ __ cmpl(len, 128);
+ __ jcc(Assembler::less, exit);
//Generate 8 constants for htbl
generateHtbl_8_block_avx2(subkeyHtbl);
@@ -4090,6 +4092,7 @@ void StubGenerator::aesgcm_avx2(Register in, Register len, Register ct, Register
__ vpxor(xmm0, xmm0, xmm0, Assembler::AVX_128bit);
__ vpxor(xmm13, xmm13, xmm13, Assembler::AVX_128bit);
+ __ bind(exit);
}
#undef __
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 3535d027dbc..868725fdb67 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -154,7 +154,8 @@ julong os::Bsd::available_memory() {
assert(kerr == KERN_SUCCESS,
"host_statistics64 failed - check mach_host_self() and count");
if (kerr == KERN_SUCCESS) {
- available = vmstat.free_count * os::vm_page_size();
+ // free_count is just a lowerbound, other page categories can be freed too and make memory available
+ available = (vmstat.free_count + vmstat.inactive_count + vmstat.purgeable_count) * os::vm_page_size();
}
#endif
return available;
diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
index 068914d7049..a9cabc87335 100644
--- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
+++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
@@ -62,7 +62,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() {
CgroupV1MemoryController* memory = nullptr;
CgroupV1Controller* cpuset = nullptr;
CgroupV1CpuController* cpu = nullptr;
- CgroupV1Controller* cpuacct = nullptr;
+ CgroupV1CpuacctController* cpuacct = nullptr;
CgroupV1Controller* pids = nullptr;
CgroupInfo cg_infos[CG_INFO_LENGTH];
u1 cg_type_flags = INVALID_CGROUPS_GENERIC;
@@ -105,9 +105,10 @@ CgroupSubsystem* CgroupSubsystemFactory::create() {
CgroupV2CpuController* cpu = new CgroupV2CpuController(CgroupV2Controller(cg_infos[CPU_IDX]._mount_path,
cg_infos[CPU_IDX]._cgroup_path,
cg_infos[CPU_IDX]._read_only));
+ CgroupV2CpuacctController* cpuacct = new CgroupV2CpuacctController(cpu);
log_debug(os, container)("Detected cgroups v2 unified hierarchy");
cleanup(cg_infos);
- return new CgroupV2Subsystem(memory, cpu, mem_other);
+ return new CgroupV2Subsystem(memory, cpu, cpuacct, mem_other);
}
/*
@@ -150,7 +151,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() {
cpu = new CgroupV1CpuController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only));
cpu->set_subsystem_path(info._cgroup_path);
} else if (strcmp(info._name, "cpuacct") == 0) {
- cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only);
+ cpuacct = new CgroupV1CpuacctController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only));
cpuacct->set_subsystem_path(info._cgroup_path);
} else if (strcmp(info._name, "pids") == 0) {
pids = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only);
@@ -856,6 +857,10 @@ jlong CgroupSubsystem::memory_soft_limit_in_bytes() {
return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem);
}
+jlong CgroupSubsystem::memory_throttle_limit_in_bytes() {
+ return memory_controller()->controller()->memory_throttle_limit_in_bytes();
+}
+
jlong CgroupSubsystem::memory_usage_in_bytes() {
return memory_controller()->controller()->memory_usage_in_bytes();
}
@@ -884,6 +889,10 @@ int CgroupSubsystem::cpu_shares() {
return cpu_controller()->controller()->cpu_shares();
}
+jlong CgroupSubsystem::cpu_usage_in_micros() {
+ return cpuacct_controller()->cpu_usage_in_micros();
+}
+
void CgroupSubsystem::print_version_specific_info(outputStream* st) {
julong phys_mem = os::Linux::physical_memory();
memory_controller()->controller()->print_version_specific_info(st, phys_mem);
diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp
index 53b178397f8..82fc87ef4f4 100644
--- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp
+++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp
@@ -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
@@ -102,6 +102,17 @@
log_trace(os, container)(log_string " is: %s", retval); \
}
+#define CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(controller, filename, key, log_string, retval) \
+{ \
+ bool is_ok; \
+ is_ok = controller->read_numerical_key_value(filename, key, &retval); \
+ if (!is_ok) { \
+ log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \
+ return OSCONTAINER_ERROR; \
+ } \
+ log_trace(os, container)(log_string " is: " JULONG_FORMAT, retval); \
+}
+
class CgroupController: public CHeapObj {
protected:
char* _cgroup_path;
@@ -216,6 +227,18 @@ class CgroupCpuController: public CHeapObj {
virtual const char* cgroup_path() = 0;
};
+// Pure virtual class representing version agnostic CPU accounting controllers
+class CgroupCpuacctController: public CHeapObj {
+ public:
+ virtual jlong cpu_usage_in_micros() = 0;
+ virtual bool needs_hierarchy_adjustment() = 0;
+ virtual bool is_read_only() = 0;
+ virtual const char* subsystem_path() = 0;
+ virtual void set_subsystem_path(const char* cgroup_path) = 0;
+ virtual const char* mount_point() = 0;
+ virtual const char* cgroup_path() = 0;
+};
+
// Pure virtual class representing version agnostic memory controllers
class CgroupMemoryController: public CHeapObj {
public:
@@ -224,6 +247,7 @@ class CgroupMemoryController: public CHeapObj {
virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0;
virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0;
virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0;
+ virtual jlong memory_throttle_limit_in_bytes() = 0;
virtual jlong memory_max_usage_in_bytes() = 0;
virtual jlong rss_usage_in_bytes() = 0;
virtual jlong cache_usage_in_bytes() = 0;
@@ -250,15 +274,19 @@ class CgroupSubsystem: public CHeapObj {
virtual const char * container_type() = 0;
virtual CachingCgroupController* memory_controller() = 0;
virtual CachingCgroupController* cpu_controller() = 0;
+ virtual CgroupCpuacctController* cpuacct_controller() = 0;
int cpu_quota();
int cpu_period();
int cpu_shares();
+ jlong cpu_usage_in_micros();
+
jlong memory_usage_in_bytes();
jlong memory_and_swap_limit_in_bytes();
jlong memory_and_swap_usage_in_bytes();
jlong memory_soft_limit_in_bytes();
+ jlong memory_throttle_limit_in_bytes();
jlong memory_max_usage_in_bytes();
jlong rss_usage_in_bytes();
jlong cache_usage_in_bytes();
diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp
index 8d9c3edb72a..ce5ef3614d1 100644
--- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp
+++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp
@@ -123,6 +123,12 @@ void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) {
}
}
+jlong CgroupV1MemoryController::uses_mem_hierarchy() {
+ julong use_hierarchy;
+ CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.use_hierarchy", "Use Hierarchy", use_hierarchy);
+ return (jlong)use_hierarchy;
+}
+
/*
* The common case, containers, we have _root == _cgroup_path, and thus set the
* controller path to the _mount_point. This is where the limits are exposed in
@@ -159,13 +165,13 @@ void verbose_log(julong read_mem_limit, julong host_mem) {
jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) {
julong memlimit;
CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit);
- if (memlimit >= phys_mem) {
- verbose_log(memlimit, phys_mem);
- return (jlong)-1;
- } else {
- verbose_log(memlimit, phys_mem);
- return (jlong)memlimit;
+ if (memlimit >= phys_mem && uses_mem_hierarchy()) {
+ CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat",
+ "hierarchical_memory_limit", "Hierarchical Memory Limit",
+ memlimit);
}
+ verbose_log(memlimit, phys_mem);
+ return (jlong)((memlimit < phys_mem) ? memlimit : -1);
}
/* read_mem_swap
@@ -183,12 +189,13 @@ jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) {
jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) {
julong memswlimit;
CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit);
- if (memswlimit >= host_total_memsw) {
- log_trace(os, container)("Memory and Swap Limit is: Unlimited");
- return (jlong)-1;
- } else {
- return (jlong)memswlimit;
+ if (memswlimit >= host_total_memsw && uses_mem_hierarchy()) {
+ CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat",
+ "hierarchical_memsw_limit", "Hierarchical Memory and Swap Limit",
+ memswlimit);
}
+ verbose_log(memswlimit, host_total_memsw);
+ return (jlong)((memswlimit < host_total_memsw) ? memswlimit : -1);
}
jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) {
@@ -248,10 +255,16 @@ jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) {
}
}
+jlong CgroupV1MemoryController::memory_throttle_limit_in_bytes() {
+ // Log this string at trace level so as to make tests happy.
+ log_trace(os, container)("Memory Throttle Limit is not supported.");
+ return OSCONTAINER_ERROR; // not supported
+}
+
// Constructor
CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset,
CgroupV1CpuController* cpu,
- CgroupV1Controller* cpuacct,
+ CgroupV1CpuacctController* cpuacct,
CgroupV1Controller* pids,
CgroupV1MemoryController* memory) :
_cpuset(cpuset),
@@ -416,6 +429,13 @@ int CgroupV1CpuController::cpu_shares() {
return shares_int;
}
+jlong CgroupV1CpuacctController::cpu_usage_in_micros() {
+ julong cpu_usage;
+ CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpuacct.usage", "CPU Usage", cpu_usage);
+ // Output is in nanoseconds, convert to microseconds.
+ return (jlong)cpu_usage / 1000;
+}
+
/* pids_max
*
* Return the maximum number of tasks available to the process
diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp
index 0c191ab91c7..a986178f5bb 100644
--- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp
+++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp
@@ -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
@@ -82,6 +82,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController {
jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override;
jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override;
jlong memory_soft_limit_in_bytes(julong upper_bound) override;
+ jlong memory_throttle_limit_in_bytes() override;
jlong memory_max_usage_in_bytes() override;
jlong rss_usage_in_bytes() override;
jlong cache_usage_in_bytes() override;
@@ -99,6 +100,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController {
const char* mount_point() override { return reader()->mount_point(); }
const char* cgroup_path() override { return reader()->cgroup_path(); }
private:
+ jlong uses_mem_hierarchy();
jlong read_mem_swappiness();
jlong read_mem_swap(julong host_total_memsw);
@@ -140,12 +142,41 @@ class CgroupV1CpuController final : public CgroupCpuController {
}
};
+class CgroupV1CpuacctController final : public CgroupCpuacctController {
+
+ private:
+ CgroupV1Controller _reader;
+ CgroupV1Controller* reader() { return &_reader; }
+ public:
+ jlong cpu_usage_in_micros() override;
+ void set_subsystem_path(const char *cgroup_path) override {
+ reader()->set_subsystem_path(cgroup_path);
+ }
+ bool is_read_only() override {
+ return reader()->is_read_only();
+ }
+ const char* subsystem_path() override {
+ return reader()->subsystem_path();
+ }
+ const char* mount_point() override {
+ return reader()->mount_point();
+ }
+ bool needs_hierarchy_adjustment() override {
+ return reader()->needs_hierarchy_adjustment();
+ }
+ const char* cgroup_path() override { return reader()->cgroup_path(); }
+
+ public:
+ CgroupV1CpuacctController(const CgroupV1Controller& reader) : _reader(reader) {
+ }
+};
+
class CgroupV1Subsystem: public CgroupSubsystem {
public:
CgroupV1Subsystem(CgroupV1Controller* cpuset,
CgroupV1CpuController* cpu,
- CgroupV1Controller* cpuacct,
+ CgroupV1CpuacctController* cpuacct,
CgroupV1Controller* pids,
CgroupV1MemoryController* memory);
@@ -165,13 +196,14 @@ class CgroupV1Subsystem: public CgroupSubsystem {
}
CachingCgroupController* memory_controller() { return _memory; }
CachingCgroupController* cpu_controller() { return _cpu; }
+ CgroupCpuacctController* cpuacct_controller() { return _cpuacct; }
private:
/* controllers */
CachingCgroupController* _memory = nullptr;
CgroupV1Controller* _cpuset = nullptr;
CachingCgroupController* _cpu = nullptr;
- CgroupV1Controller* _cpuacct = nullptr;
+ CgroupV1CpuacctController* _cpuacct = nullptr;
CgroupV1Controller* _pids = nullptr;
};
diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp
index cbadbb9db02..6472fdfccc5 100644
--- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp
+++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, 2025, 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
@@ -114,12 +115,14 @@ int CgroupV2CpuController::cpu_quota() {
// Constructor
CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory,
CgroupV2CpuController* cpu,
+ CgroupV2CpuacctController* cpuacct,
CgroupV2Controller unified) :
_unified(unified) {
CgroupUtil::adjust_controller(memory);
CgroupUtil::adjust_controller(cpu);
_memory = new CachingCgroupController(memory);
_cpu = new CachingCgroupController(cpu);
+ _cpuacct = cpuacct;
}
bool CgroupV2Subsystem::is_containerized() {
@@ -152,6 +155,17 @@ int CgroupV2CpuController::cpu_period() {
return period;
}
+jlong CgroupV2CpuController::cpu_usage_in_micros() {
+ julong cpu_usage;
+ bool is_ok = reader()->read_numerical_key_value("/cpu.stat", "usage_usec", &cpu_usage);
+ if (!is_ok) {
+ log_trace(os, container)("CPU Usage failed: %d", OSCONTAINER_ERROR);
+ return OSCONTAINER_ERROR;
+ }
+ log_trace(os, container)("CPU Usage is: " JULONG_FORMAT, cpu_usage);
+ return (jlong)cpu_usage;
+}
+
/* memory_usage_in_bytes
*
* Return the amount of used memory used by this cgroup and descendents
@@ -173,10 +187,16 @@ jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) {
return mem_soft_limit;
}
+jlong CgroupV2MemoryController::memory_throttle_limit_in_bytes() {
+ jlong mem_throttle_limit;
+ CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.high", "Memory Throttle Limit", mem_throttle_limit);
+ return mem_throttle_limit;
+}
+
jlong CgroupV2MemoryController::memory_max_usage_in_bytes() {
- // Log this string at trace level so as to make tests happy.
- log_trace(os, container)("Maximum Memory Usage is not supported.");
- return OSCONTAINER_ERROR; // not supported
+ julong mem_max_usage;
+ CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.peak", "Maximum Memory Usage", mem_max_usage);
+ return mem_max_usage;
}
jlong CgroupV2MemoryController::rss_usage_in_bytes() {
diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp
index 56dcadd670f..e26f37925ca 100644
--- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp
+++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, 2024, 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
@@ -61,6 +62,34 @@ class CgroupV2CpuController: public CgroupCpuController {
int cpu_quota() override;
int cpu_period() override;
int cpu_shares() override;
+ jlong cpu_usage_in_micros();
+ bool is_read_only() override {
+ return reader()->is_read_only();
+ }
+ const char* subsystem_path() override {
+ return reader()->subsystem_path();
+ }
+ bool needs_hierarchy_adjustment() override {
+ return reader()->needs_hierarchy_adjustment();
+ }
+ void set_subsystem_path(const char* cgroup_path) override {
+ reader()->set_subsystem_path(cgroup_path);
+ }
+ const char* mount_point() override { return reader()->mount_point(); }
+ const char* cgroup_path() override { return reader()->cgroup_path(); }
+};
+
+class CgroupV2CpuacctController: public CgroupCpuacctController {
+ private:
+ CgroupV2CpuController* _reader;
+ CgroupV2CpuController* reader() { return _reader; }
+ public:
+ CgroupV2CpuacctController(CgroupV2CpuController* reader) : _reader(reader) {
+ }
+ // In cgroup v2, cpu usage is a part of the cpu controller.
+ jlong cpu_usage_in_micros() override {
+ return reader()->cpu_usage_in_micros();
+ }
bool is_read_only() override {
return reader()->is_read_only();
}
@@ -89,6 +118,7 @@ class CgroupV2MemoryController final: public CgroupMemoryController {
jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override;
jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override;
jlong memory_soft_limit_in_bytes(julong upper_bound) override;
+ jlong memory_throttle_limit_in_bytes() override;
jlong memory_usage_in_bytes() override;
jlong memory_max_usage_in_bytes() override;
jlong rss_usage_in_bytes() override;
@@ -118,11 +148,14 @@ class CgroupV2Subsystem: public CgroupSubsystem {
CachingCgroupController* _memory = nullptr;
CachingCgroupController* _cpu = nullptr;
+ CgroupCpuacctController* _cpuacct = nullptr;
+
CgroupV2Controller* unified() { return &_unified; }
public:
CgroupV2Subsystem(CgroupV2MemoryController * memory,
CgroupV2CpuController* cpu,
+ CgroupV2CpuacctController* cpuacct,
CgroupV2Controller unified);
char * cpu_cpuset_cpus() override;
@@ -137,6 +170,7 @@ class CgroupV2Subsystem: public CgroupSubsystem {
}
CachingCgroupController* memory_controller() override { return _memory; }
CachingCgroupController* cpu_controller() override { return _cpu; }
+ CgroupCpuacctController* cpuacct_controller() override { return _cpuacct; };
};
#endif // CGROUP_V2_SUBSYSTEM_LINUX_HPP
diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp
index ecac7307c30..2ba4c252659 100644
--- a/src/hotspot/os/linux/osContainer_linux.cpp
+++ b/src/hotspot/os/linux/osContainer_linux.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -122,6 +122,11 @@ jlong OSContainer::memory_soft_limit_in_bytes() {
return cgroup_subsystem->memory_soft_limit_in_bytes();
}
+jlong OSContainer::memory_throttle_limit_in_bytes() {
+ assert(cgroup_subsystem != nullptr, "cgroup subsystem not available");
+ return cgroup_subsystem->memory_throttle_limit_in_bytes();
+}
+
jlong OSContainer::memory_usage_in_bytes() {
assert(cgroup_subsystem != nullptr, "cgroup subsystem not available");
return cgroup_subsystem->memory_usage_in_bytes();
@@ -177,6 +182,11 @@ int OSContainer::cpu_shares() {
return cgroup_subsystem->cpu_shares();
}
+jlong OSContainer::cpu_usage_in_micros() {
+ assert(cgroup_subsystem != nullptr, "cgroup subsystem not available");
+ return cgroup_subsystem->cpu_usage_in_micros();
+}
+
jlong OSContainer::pids_max() {
assert(cgroup_subsystem != nullptr, "cgroup subsystem not available");
return cgroup_subsystem->pids_max();
diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp
index dd29c7a4769..3c270e8ea50 100644
--- a/src/hotspot/os/linux/osContainer_linux.hpp
+++ b/src/hotspot/os/linux/osContainer_linux.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -54,6 +54,7 @@ class OSContainer: AllStatic {
static jlong memory_and_swap_limit_in_bytes();
static jlong memory_and_swap_usage_in_bytes();
static jlong memory_soft_limit_in_bytes();
+ static jlong memory_throttle_limit_in_bytes();
static jlong memory_usage_in_bytes();
static jlong memory_max_usage_in_bytes();
static jlong rss_usage_in_bytes();
@@ -69,6 +70,8 @@ class OSContainer: AllStatic {
static int cpu_shares();
+ static jlong cpu_usage_in_micros();
+
static jlong pids_max();
static jlong pids_current();
};
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 49125ae8954..fc0578f4d9b 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -478,13 +478,11 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu
}
#ifndef SYS_gettid
-// i386: 224, amd64: 186, sparc: 143
+// i386: 224, amd64: 186
#if defined(__i386__)
#define SYS_gettid 224
#elif defined(__amd64__)
#define SYS_gettid 186
- #elif defined(__sparc__)
- #define SYS_gettid 143
#else
#error "Define SYS_gettid for this architecture"
#endif
@@ -2470,6 +2468,7 @@ void os::Linux::print_uptime_info(outputStream* st) {
if (ret == 0) {
os::print_dhm(st, "OS uptime:", (long) sinfo.uptime);
}
+ assert(ret == 0, "sysinfo failed: %s", os::strerror(errno));
}
bool os::Linux::print_container_info(outputStream* st) {
@@ -2527,9 +2526,18 @@ bool os::Linux::print_container_info(outputStream* st) {
st->print_cr("%s", i == OSCONTAINER_ERROR ? "not supported" : "no shares");
}
+ jlong j = OSContainer::cpu_usage_in_micros();
+ st->print("cpu_usage_in_micros: ");
+ if (j >= 0) {
+ st->print_cr(JLONG_FORMAT, j);
+ } else {
+ st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "no usage");
+ }
+
OSContainer::print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes");
OSContainer::print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes");
OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes");
+ OSContainer::print_container_helper(st, OSContainer::memory_throttle_limit_in_bytes(), "memory_throttle_limit_in_bytes");
OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes");
OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes");
OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes");
@@ -2537,7 +2545,7 @@ bool os::Linux::print_container_info(outputStream* st) {
OSContainer::print_version_specific_info(st);
- jlong j = OSContainer::pids_max();
+ j = OSContainer::pids_max();
st->print("maximum number of tasks: ");
if (j > 0) {
st->print_cr(JLONG_FORMAT, j);
@@ -2583,16 +2591,18 @@ void os::print_memory_info(outputStream* st) {
// values in struct sysinfo are "unsigned long"
struct sysinfo si;
- sysinfo(&si);
-
+ int ret = sysinfo(&si);
+ assert(ret == 0, "sysinfo failed: %s", os::strerror(errno));
st->print(", physical " UINT64_FORMAT "k",
os::physical_memory() >> 10);
st->print("(" UINT64_FORMAT "k free)",
os::available_memory() >> 10);
- st->print(", swap " UINT64_FORMAT "k",
- ((jlong)si.totalswap * si.mem_unit) >> 10);
- st->print("(" UINT64_FORMAT "k free)",
- ((jlong)si.freeswap * si.mem_unit) >> 10);
+ if (ret == 0) {
+ st->print(", swap " UINT64_FORMAT "k",
+ ((jlong)si.totalswap * si.mem_unit) >> 10);
+ st->print("(" UINT64_FORMAT "k free)",
+ ((jlong)si.freeswap * si.mem_unit) >> 10);
+ }
st->cr();
st->print("Page Sizes: ");
_page_sizes.print_on(st);
@@ -2724,8 +2734,6 @@ const char* search_string = "CPU";
const char* search_string = "cpu";
#elif defined(S390)
const char* search_string = "machine =";
-#elif defined(SPARC)
-const char* search_string = "cpu";
#else
const char* search_string = "Processor";
#endif
@@ -2777,8 +2785,6 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
strncpy(cpuinfo, LP64_ONLY("RISCV64") NOT_LP64("RISCV32"), length);
#elif defined(S390)
strncpy(cpuinfo, "S390", length);
-#elif defined(SPARC)
- strncpy(cpuinfo, "sparcv9", length);
#elif defined(ZERO_LIBARCH)
strncpy(cpuinfo, ZERO_LIBARCH, length);
#else
@@ -5261,7 +5267,7 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
if (core_pattern[0] == '|') {
written = jio_snprintf(buffer, bufferSize,
- "\"%s\" (or dumping to %s/core.%d)",
+ "\"%s\" (alternatively, falling back to %s/core.%d)",
&core_pattern[1], p, current_process_id());
} else if (pid_pos != nullptr) {
*pid_pos = '\0';
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index 448ebce620a..d0c82135797 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -107,41 +107,60 @@ size_t os::_os_min_stack_allowed = PTHREAD_STACK_MIN;
// Check core dump limit and report possible place where core can be found
void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool check_only) {
+ stringStream buf(buffer, bufferSize);
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
- jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
- VMError::record_coredump_status(buffer, false);
+ buf.print("CreateCoredumpOnCrash is disabled from command line");
+ VMError::record_coredump_status(buf.freeze(), false);
} else {
struct rlimit rlim;
bool success = true;
bool warn = true;
char core_path[PATH_MAX];
if (get_core_path(core_path, PATH_MAX) <= 0) {
- jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id());
+ // In the warning message, let the user know.
+ if (check_only) {
+ buf.print("the core path couldn't be determined. It commonly defaults to ");
+ }
+ buf.print("core.%d%s", current_process_id(), check_only ? "" : " (may not exist)");
#ifdef LINUX
} else if (core_path[0] == '"') { // redirect to user process
- jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path);
+ if (check_only) {
+ buf.print("core dumps may be further processed by the following: ");
+ } else {
+ buf.print("Determined by the following: ");
+ }
+ buf.print("%s", core_path);
#endif
} else if (getrlimit(RLIMIT_CORE, &rlim) != 0) {
- jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path);
+ if (check_only) {
+ buf.print("the rlimit couldn't be determined. If resource limits permit, the core dump will be located at ");
+ }
+ buf.print("%s%s", core_path, check_only ? "" : " (may not exist)");
} else {
switch(rlim.rlim_cur) {
case RLIM_INFINITY:
- jio_snprintf(buffer, bufferSize, "%s", core_path);
+ buf.print("%s", core_path);
warn = false;
break;
case 0:
- jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again");
+ buf.print("%s dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again", check_only ? "core" : "Core");
success = false;
break;
default:
- jio_snprintf(buffer, bufferSize, "%s (max size " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, uint64_t(rlim.rlim_cur) / K);
+ if (check_only) {
+ buf.print("core dumps are constrained ");
+ } else {
+ buf.print( "%s ", core_path);
+ }
+ buf.print( "(max size " UINT64_FORMAT " k). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", uint64_t(rlim.rlim_cur) / K);
break;
}
}
+ const char* result = buf.freeze();
if (!check_only) {
- VMError::record_coredump_status(buffer, success);
+ VMError::record_coredump_status(result, success);
} else if (warn) {
- warning("CreateCoredumpOnCrash specified, but %s", buffer);
+ warning("CreateCoredumpOnCrash specified, but %s", result);
}
}
}
diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp
index cbbecea3a6a..e3483781794 100644
--- a/src/hotspot/os/posix/perfMemory_posix.cpp
+++ b/src/hotspot/os/posix/perfMemory_posix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026 SAP SE. 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
@@ -950,7 +950,7 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
if (result == -1 ) break;
if (!os::write(fd, &zero_int, 1)) {
if (errno == ENOSPC) {
- warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
+ warning("Insufficient space for shared memory file: %s/%s\n", dirname, filename);
}
result = OS_ERR;
break;
diff --git a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp
index 722dffc150d..9a314667fcb 100644
--- a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp
+++ b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,395 +23,5 @@
*
*/
-#ifndef OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
-#define OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
-
-#ifndef PPC64
-#error "Atomic currently only implemented for PPC64"
-#endif
-
-#include "orderAccess_aix_ppc.hpp"
-#include "utilities/debug.hpp"
-
-// Implementation of class atomic
-
-//
-// machine barrier instructions:
-//
-// - sync two-way memory barrier, aka fence
-// - lwsync orders Store|Store,
-// Load|Store,
-// Load|Load,
-// but not Store|Load
-// - eieio orders memory accesses for device memory (only)
-// - isync invalidates speculatively executed instructions
-// From the POWER ISA 2.06 documentation:
-// "[...] an isync instruction prevents the execution of
-// instructions following the isync until instructions
-// preceding the isync have completed, [...]"
-// From IBM's AIX assembler reference:
-// "The isync [...] instructions causes the processor to
-// refetch any instructions that might have been fetched
-// prior to the isync instruction. The instruction isync
-// causes the processor to wait for all previous instructions
-// to complete. Then any instructions already fetched are
-// discarded and instruction processing continues in the
-// environment established by the previous instructions."
-//
-// semantic barrier instructions:
-// (as defined in orderAccess.hpp)
-//
-// - release orders Store|Store, (maps to lwsync)
-// Load|Store
-// - acquire orders Load|Store, (maps to lwsync)
-// Load|Load
-// - fence orders Store|Store, (maps to sync)
-// Load|Store,
-// Load|Load,
-// Store|Load
-//
-
-inline void pre_membar(atomic_memory_order order) {
- switch (order) {
- case memory_order_relaxed:
- case memory_order_acquire: break;
- case memory_order_release:
- case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break;
- default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
- }
-}
-
-inline void post_membar(atomic_memory_order order) {
- switch (order) {
- case memory_order_relaxed:
- case memory_order_release: break;
- case memory_order_acquire:
- case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break;
- default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
- }
-}
-
-
-template
-struct Atomic::PlatformAdd {
- template
- D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
-
- template
- D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
- return add_then_fetch(dest, add_value, order) - add_value;
- }
-};
-
-template<>
-template
-inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(4 == sizeof(I));
- STATIC_ASSERT(4 == sizeof(D));
-
- D result;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- "1: lwarx %0, 0, %2 \n"
- " add %0, %0, %1 \n"
- " stwcx. %0, 0, %2 \n"
- " bne- 1b \n"
- : /*%0*/"=&r" (result)
- : /*%1*/"r" (add_value), /*%2*/"r" (dest)
- : "cc", "memory" );
-
- post_membar(order);
-
- return result;
-}
-
-
-template<>
-template
-inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(I));
- STATIC_ASSERT(8 == sizeof(D));
-
- D result;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- "1: ldarx %0, 0, %2 \n"
- " add %0, %0, %1 \n"
- " stdcx. %0, 0, %2 \n"
- " bne- 1b \n"
- : /*%0*/"=&r" (result)
- : /*%1*/"r" (add_value), /*%2*/"r" (dest)
- : "cc", "memory" );
-
- post_membar(order);
-
- return result;
-}
-
-template<>
-template
-inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
- T exchange_value,
- atomic_memory_order order) const {
- // Note that xchg doesn't necessarily do an acquire
- // (see synchronizer.cpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* atomic loop */
- "1: \n"
- " lwarx %[old_value], %[dest], %[zero] \n"
- " stwcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(T));
- // Note that xchg doesn't necessarily do an acquire
- // (see synchronizer.cpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* atomic loop */
- "1: \n"
- " ldarx %[old_value], %[dest], %[zero] \n"
- " stdcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(1 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- // Using 32 bit internally.
- volatile int *dest_base = (volatile int*)((uintptr_t)dest & ~3);
-
-#ifdef VM_LITTLE_ENDIAN
- const unsigned int shift_amount = ((uintptr_t)dest & 3) * 8;
-#else
- const unsigned int shift_amount = ((~(uintptr_t)dest) & 3) * 8;
-#endif
- const unsigned int masked_compare_val = ((unsigned int)(unsigned char)compare_value),
- masked_exchange_val = ((unsigned int)(unsigned char)exchange_value),
- xor_value = (masked_compare_val ^ masked_exchange_val) << shift_amount;
-
- unsigned int old_value, value32;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* simple guard */
- " lbz %[old_value], 0(%[dest]) \n"
- " cmpw %[masked_compare_val], %[old_value] \n"
- " bne- 2f \n"
- /* atomic loop */
- "1: \n"
- " lwarx %[value32], 0, %[dest_base] \n"
- /* extract byte and compare */
- " srd %[old_value], %[value32], %[shift_amount] \n"
- " clrldi %[old_value], %[old_value], 56 \n"
- " cmpw %[masked_compare_val], %[old_value] \n"
- " bne- 2f \n"
- /* replace byte and try to store */
- " xor %[value32], %[xor_value], %[value32] \n"
- " stwcx. %[value32], 0, %[dest_base] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- [value32] "=&r" (value32),
- "=m" (*dest),
- "=m" (*dest_base)
- /* in */
- : [dest] "b" (dest),
- [dest_base] "b" (dest_base),
- [shift_amount] "r" (shift_amount),
- [masked_compare_val] "r" (masked_compare_val),
- [xor_value] "r" (xor_value),
- "m" (*dest),
- "m" (*dest_base)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return PrimitiveConversions::cast((unsigned char)old_value);
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(4 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* simple guard */
- " lwz %[old_value], 0(%[dest]) \n"
- " cmpw %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- /* atomic loop */
- "1: \n"
- " lwarx %[old_value], %[dest], %[zero] \n"
- " cmpw %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- " stwcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [compare_value] "r" (compare_value),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* simple guard */
- " ld %[old_value], 0(%[dest]) \n"
- " cmpd %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- /* atomic loop */
- "1: \n"
- " ldarx %[old_value], %[dest], %[zero] \n"
- " cmpd %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- " stdcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [compare_value] "r" (compare_value),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template
-struct Atomic::PlatformOrderedLoad {
- template
- T operator()(const volatile T* p) const {
- T t = Atomic::load(p);
- // Use twi-isync for load_acquire (faster than lwsync).
- __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory");
- return t;
- }
-};
-
-#endif // OS_CPU_AIX_PPC_ATOMIC_AIX_PPC_HPP
+// Including inline assembler functions that are shared between multiple PPC64 platforms.
+#include "atomicAccess_ppc.hpp"
diff --git a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp
index 9ca6c18d5bb..d395add6d69 100644
--- a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp
+++ b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,62 +23,5 @@
*
*/
-#ifndef OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP
-#define OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP
-
-// Included in orderAccess.hpp header file.
-
-// Compiler version last used for testing: xlc 12
-// Please update this information when this file changes
-
-// Implementation of class OrderAccess.
-
-//
-// Machine barrier instructions:
-//
-// - sync Two-way memory barrier, aka fence.
-// - lwsync orders Store|Store,
-// Load|Store,
-// Load|Load,
-// but not Store|Load
-// - eieio orders Store|Store
-// - isync Invalidates speculatively executed instructions,
-// but isync may complete before storage accesses
-// associated with instructions preceding isync have
-// been performed.
-//
-// Semantic barrier instructions:
-// (as defined in orderAccess.hpp)
-//
-// - release orders Store|Store, (maps to lwsync)
-// Load|Store
-// - acquire orders Load|Store, (maps to lwsync)
-// Load|Load
-// - fence orders Store|Store, (maps to sync)
-// Load|Store,
-// Load|Load,
-// Store|Load
-//
-
-#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory");
-#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory");
-#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
-#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory");
-
-inline void OrderAccess::loadload() { inlasm_lwsync(); }
-inline void OrderAccess::storestore() { inlasm_lwsync(); }
-inline void OrderAccess::loadstore() { inlasm_lwsync(); }
-inline void OrderAccess::storeload() { inlasm_sync(); }
-
-inline void OrderAccess::acquire() { inlasm_lwsync(); }
-inline void OrderAccess::release() { inlasm_lwsync(); }
-inline void OrderAccess::fence() { inlasm_sync(); }
-inline void OrderAccess::cross_modify_fence_impl()
- { inlasm_isync(); }
-
-#undef inlasm_sync
-#undef inlasm_lwsync
-#undef inlasm_eieio
-#undef inlasm_isync
-
-#endif // OS_CPU_AIX_PPC_ORDERACCESS_AIX_PPC_HPP
+// Including inline assembler functions that are shared between multiple PPC64 platforms.
+#include "orderAccess_ppc.hpp"
diff --git a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp
index 1e4eb37cdac..9a314667fcb 100644
--- a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp
+++ b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,373 +23,5 @@
*
*/
-#ifndef OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
-#define OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
-
-#ifndef PPC64
-#error "Atomic currently only implemented for PPC64"
-#endif
-
-#include "orderAccess_linux_ppc.hpp"
-#include "utilities/debug.hpp"
-
-// Implementation of class atomic
-
-//
-// machine barrier instructions:
-//
-// - sync two-way memory barrier, aka fence
-// - lwsync orders Store|Store,
-// Load|Store,
-// Load|Load,
-// but not Store|Load
-// - eieio orders memory accesses for device memory (only)
-// - isync invalidates speculatively executed instructions
-// From the POWER ISA 2.06 documentation:
-// "[...] an isync instruction prevents the execution of
-// instructions following the isync until instructions
-// preceding the isync have completed, [...]"
-// From IBM's AIX assembler reference:
-// "The isync [...] instructions causes the processor to
-// refetch any instructions that might have been fetched
-// prior to the isync instruction. The instruction isync
-// causes the processor to wait for all previous instructions
-// to complete. Then any instructions already fetched are
-// discarded and instruction processing continues in the
-// environment established by the previous instructions."
-//
-// semantic barrier instructions:
-// (as defined in orderAccess.hpp)
-//
-// - release orders Store|Store, (maps to lwsync)
-// Load|Store
-// - acquire orders Load|Store, (maps to lwsync)
-// Load|Load
-// - fence orders Store|Store, (maps to sync)
-// Load|Store,
-// Load|Load,
-// Store|Load
-//
-
-inline void pre_membar(atomic_memory_order order) {
- switch (order) {
- case memory_order_relaxed:
- case memory_order_acquire: break;
- case memory_order_release:
- case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break;
- default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
- }
-}
-
-inline void post_membar(atomic_memory_order order) {
- switch (order) {
- case memory_order_relaxed:
- case memory_order_release: break;
- case memory_order_acquire:
- case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break;
- default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
- }
-}
-
-
-template
-struct Atomic::PlatformAdd {
- template
- D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
-
- template
- D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
- return add_then_fetch(dest, add_value, order) - add_value;
- }
-};
-
-template<>
-template
-inline D Atomic::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(4 == sizeof(I));
- STATIC_ASSERT(4 == sizeof(D));
-
- D result;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- "1: lwarx %0, 0, %2 \n"
- " add %0, %0, %1 \n"
- " stwcx. %0, 0, %2 \n"
- " bne- 1b \n"
- : /*%0*/"=&r" (result)
- : /*%1*/"r" (add_value), /*%2*/"r" (dest)
- : "cc", "memory" );
-
- post_membar(order);
-
- return result;
-}
-
-
-template<>
-template
-inline D Atomic::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(I));
- STATIC_ASSERT(8 == sizeof(D));
-
- D result;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- "1: ldarx %0, 0, %2 \n"
- " add %0, %0, %1 \n"
- " stdcx. %0, 0, %2 \n"
- " bne- 1b \n"
- : /*%0*/"=&r" (result)
- : /*%1*/"r" (add_value), /*%2*/"r" (dest)
- : "cc", "memory" );
-
- post_membar(order);
-
- return result;
-}
-
-template<>
-template
-inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
- T exchange_value,
- atomic_memory_order order) const {
- // Note that xchg doesn't necessarily do an acquire
- // (see synchronizer.cpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* atomic loop */
- "1: \n"
- " lwarx %[old_value], %[dest], %[zero] \n"
- " stwcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(T));
- // Note that xchg doesn't necessarily do an acquire
- // (see synchronizer.cpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* atomic loop */
- "1: \n"
- " ldarx %[old_value], %[dest], %[zero] \n"
- " stdcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(1 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- // Using 32 bit internally.
- unsigned int old_value, loaded_value;
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* atomic loop */
- "1: \n"
- " lbarx %[old_value], 0, %[dest] \n"
- /* extract byte and compare */
- " cmpw %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- /* replace byte and try to store */
- " stbcx. %[exchange_value], 0, %[dest] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- [loaded_value] "=&r" (loaded_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [compare_value] "r" (compare_value),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return PrimitiveConversions::cast((unsigned char)old_value);
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(4 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* simple guard */
- " lwz %[old_value], 0(%[dest]) \n"
- " cmpw %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- /* atomic loop */
- "1: \n"
- " lwarx %[old_value], %[dest], %[zero] \n"
- " cmpw %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- " stwcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [compare_value] "r" (compare_value),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template<>
-template
-inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
- T compare_value,
- T exchange_value,
- atomic_memory_order order) const {
- STATIC_ASSERT(8 == sizeof(T));
-
- // Note that cmpxchg guarantees a two-way memory barrier across
- // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
- // specified otherwise (see atomic.hpp).
-
- T old_value;
- const uint64_t zero = 0;
-
- pre_membar(order);
-
- __asm__ __volatile__ (
- /* simple guard */
- " ld %[old_value], 0(%[dest]) \n"
- " cmpd %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- /* atomic loop */
- "1: \n"
- " ldarx %[old_value], %[dest], %[zero] \n"
- " cmpd %[compare_value], %[old_value] \n"
- " bne- 2f \n"
- " stdcx. %[exchange_value], %[dest], %[zero] \n"
- " bne- 1b \n"
- /* exit */
- "2: \n"
- /* out */
- : [old_value] "=&r" (old_value),
- "=m" (*dest)
- /* in */
- : [dest] "b" (dest),
- [zero] "r" (zero),
- [compare_value] "r" (compare_value),
- [exchange_value] "r" (exchange_value),
- "m" (*dest)
- /* clobber */
- : "cc",
- "memory"
- );
-
- post_membar(order);
-
- return old_value;
-}
-
-template
-struct Atomic::PlatformOrderedLoad
-{
- template
- T operator()(const volatile T* p) const {
- T t = Atomic::load(p);
- // Use twi-isync for load_acquire (faster than lwsync).
- __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory");
- return t;
- }
-};
-
-#endif // OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
+// Including inline assembler functions that are shared between multiple PPC64 platforms.
+#include "atomicAccess_ppc.hpp"
diff --git a/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp
index 2e6eb1f3878..d395add6d69 100644
--- a/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp
+++ b/src/hotspot/os_cpu/linux_ppc/orderAccess_linux_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,66 +23,5 @@
*
*/
-#ifndef OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP
-#define OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP
-
-// Included in orderAccess.hpp header file.
-
-#ifndef PPC64
-#error "OrderAccess currently only implemented for PPC64"
-#endif
-
-// Compiler version last used for testing: gcc 4.1.2
-// Please update this information when this file changes
-
-// Implementation of class OrderAccess.
-
-//
-// Machine barrier instructions:
-//
-// - sync Two-way memory barrier, aka fence.
-// - lwsync orders Store|Store,
-// Load|Store,
-// Load|Load,
-// but not Store|Load
-// - eieio orders Store|Store
-// - isync Invalidates speculatively executed instructions,
-// but isync may complete before storage accesses
-// associated with instructions preceding isync have
-// been performed.
-//
-// Semantic barrier instructions:
-// (as defined in orderAccess.hpp)
-//
-// - release orders Store|Store, (maps to lwsync)
-// Load|Store
-// - acquire orders Load|Store, (maps to lwsync)
-// Load|Load
-// - fence orders Store|Store, (maps to sync)
-// Load|Store,
-// Load|Load,
-// Store|Load
-//
-
-#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory");
-#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory");
-#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
-#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory");
-
-inline void OrderAccess::loadload() { inlasm_lwsync(); }
-inline void OrderAccess::storestore() { inlasm_lwsync(); }
-inline void OrderAccess::loadstore() { inlasm_lwsync(); }
-inline void OrderAccess::storeload() { inlasm_sync(); }
-
-inline void OrderAccess::acquire() { inlasm_lwsync(); }
-inline void OrderAccess::release() { inlasm_lwsync(); }
-inline void OrderAccess::fence() { inlasm_sync(); }
-inline void OrderAccess::cross_modify_fence_impl()
- { inlasm_isync(); }
-
-#undef inlasm_sync
-#undef inlasm_lwsync
-#undef inlasm_eieio
-#undef inlasm_isync
-
-#endif // OS_CPU_LINUX_PPC_ORDERACCESS_LINUX_PPC_HPP
+// Including inline assembler functions that are shared between multiple PPC64 platforms.
+#include "orderAccess_ppc.hpp"
diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp
index e2760689daa..57d22a38324 100644
--- a/src/hotspot/share/c1/c1_Runtime1.cpp
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp
@@ -818,7 +818,7 @@ JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request))
Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request);
if (action == Deoptimization::Action_make_not_entrant) {
- if (nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize)) {
+ if (nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE)) {
if (reason == Deoptimization::Reason_tenured) {
MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/);
if (trap_mdo != nullptr) {
@@ -1110,7 +1110,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id ))
// safepoint, but if it's still alive then make it not_entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) {
- nm->make_not_entrant(nmethod::ChangeReason::C1_codepatch);
+ nm->make_not_entrant(nmethod::InvalidationReason::C1_CODEPATCH);
}
Deoptimization::deoptimize_frame(current, caller_frame.id());
@@ -1358,7 +1358,7 @@ void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) {
// Make sure the nmethod is invalidated, i.e. made not entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) {
- nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize_for_patching);
+ nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING);
}
}
@@ -1486,7 +1486,7 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current))
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
assert (nm != nullptr, "no more nmethod?");
- nm->make_not_entrant(nmethod::ChangeReason::C1_predicate_failed_trap);
+ nm->make_not_entrant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP);
methodHandle m(current, nm->method());
MethodData* mdo = m->method_data();
diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp
index b1072dbce9b..498ce6255e4 100644
--- a/src/hotspot/share/cds/dynamicArchive.cpp
+++ b/src/hotspot/share/cds/dynamicArchive.cpp
@@ -348,6 +348,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio
assert(dynamic_info != nullptr, "Sanity");
dynamic_info->open_as_output();
+ dynamic_info->prepare_for_writing();
ArchiveHeapInfo no_heap_for_dynamic_dump;
ArchiveBuilder::write_archive(dynamic_info, &no_heap_for_dynamic_dump);
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index a413aa2d8e8..80dfa5f19f3 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -766,7 +766,9 @@ void FileMapInfo::open_as_output() {
}
_fd = fd;
_file_open = true;
+}
+void FileMapInfo::prepare_for_writing() {
// Seek past the header. We will write the header after all regions are written
// and their CRCs computed.
size_t header_bytes = header()->header_size();
diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp
index e0b33fc8245..a567d59a7cd 100644
--- a/src/hotspot/share/cds/filemap.hpp
+++ b/src/hotspot/share/cds/filemap.hpp
@@ -359,6 +359,7 @@ class FileMapInfo : public CHeapObj {
// File manipulation.
bool open_as_input() NOT_CDS_RETURN_(false);
void open_as_output();
+ void prepare_for_writing();
void write_header();
void write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec);
diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp
index d6a51c87513..acaa05794a3 100644
--- a/src/hotspot/share/cds/lambdaFormInvokers.cpp
+++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp
@@ -191,7 +191,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
// make a copy of class bytes so GC will not affect us.
char *buf = NEW_RESOURCE_ARRAY(char, len);
memcpy(buf, (char*)h_bytes->byte_at_addr(0), len);
- ClassFileStream st((u1*)buf, len, nullptr);
+ ClassFileStream st((u1*)buf, len, "jrt:/java.base");
regenerate_class(class_name, st, CHECK);
}
}
diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp
index 1d1214b77bb..2db7a3116a6 100644
--- a/src/hotspot/share/cds/metaspaceShared.cpp
+++ b/src/hotspot/share/cds/metaspaceShared.cpp
@@ -113,6 +113,7 @@ intx MetaspaceShared::_relocation_delta;
char* MetaspaceShared::_requested_base_address;
Array* MetaspaceShared::_archived_method_handle_intrinsics = nullptr;
bool MetaspaceShared::_use_optimized_module_handling = true;
+FileMapInfo* MetaspaceShared::_output_mapinfo = nullptr;
// The CDS archive is divided into the following regions:
// rw - read-write metadata
@@ -321,6 +322,24 @@ void MetaspaceShared::initialize_for_static_dump() {
MetaspaceShared::unrecoverable_writing_error();
}
_symbol_region.init(&_symbol_rs, &_symbol_vs);
+ if (CDSConfig::is_dumping_preimage_static_archive()) {
+ // We are in the AOT training run. User code is executed.
+ //
+ // On Windows, if the user code closes System.out and we open the AOT config file for output
+ // only at VM exit, we might get back the same file HANDLE as stdout, and the AOT config
+ // file may get corrupted by UL logs. By opening early, we ensure that the output
+ // HANDLE is different than stdout so we can avoid such corruption.
+ open_output_mapinfo();
+ } else {
+ // No need for the above as we won't execute any user code.
+ }
+}
+
+void MetaspaceShared::open_output_mapinfo() {
+ const char* static_archive = CDSConfig::output_archive_path();
+ assert(static_archive != nullptr, "sanity");
+ _output_mapinfo = new FileMapInfo(static_archive, true);
+ _output_mapinfo->open_as_output();
}
// Called by universe_post_init()
@@ -551,14 +570,13 @@ class VM_PopulateDumpSharedSpace : public VM_Operation {
public:
- VM_PopulateDumpSharedSpace(StaticArchiveBuilder& b) :
- VM_Operation(), _heap_info(), _map_info(nullptr), _builder(b) {}
+ VM_PopulateDumpSharedSpace(StaticArchiveBuilder& b, FileMapInfo* map_info) :
+ VM_Operation(), _heap_info(), _map_info(map_info), _builder(b) {}
bool skip_operation() const { return false; }
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
ArchiveHeapInfo* heap_info() { return &_heap_info; }
- FileMapInfo* map_info() const { return _map_info; }
void doit(); // outline because gdb sucks
bool allow_nested_vm_operations() const { return true; }
}; // class VM_PopulateDumpSharedSpace
@@ -688,12 +706,6 @@ void VM_PopulateDumpSharedSpace::doit() {
CppVtables::zero_archived_vtables();
// Write the archive file
- if (CDSConfig::is_dumping_final_static_archive()) {
- FileMapInfo::free_current_info(); // FIXME: should not free current info
- }
- const char* static_archive = CDSConfig::output_archive_path();
- assert(static_archive != nullptr, "sanity");
- _map_info = new FileMapInfo(static_archive, true);
_map_info->populate_header(MetaspaceShared::core_region_alignment());
_map_info->set_early_serialized_data(early_serialized_data);
_map_info->set_serialized_data(serialized_data);
@@ -1012,7 +1024,14 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS
}
#endif
- VM_PopulateDumpSharedSpace op(builder);
+ if (!CDSConfig::is_dumping_preimage_static_archive()) {
+ if (CDSConfig::is_dumping_final_static_archive()) {
+ FileMapInfo::free_current_info(); // FIXME: should not free current info
+ }
+ open_output_mapinfo();
+ }
+
+ VM_PopulateDumpSharedSpace op(builder, _output_mapinfo);
VMThread::execute(&op);
if (AOTCodeCache::is_on_for_dump() && CDSConfig::is_dumping_final_static_archive()) {
@@ -1026,7 +1045,9 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS
CDSConfig::disable_dumping_aot_code();
}
- bool status = write_static_archive(&builder, op.map_info(), op.heap_info());
+ bool status = write_static_archive(&builder, _output_mapinfo, op.heap_info());
+ assert(!_output_mapinfo->is_open(), "Must be closed already");
+ _output_mapinfo = nullptr;
if (status && CDSConfig::is_dumping_preimage_static_archive()) {
tty->print_cr("%s AOTConfiguration recorded: %s",
CDSConfig::has_temp_aot_config_file() ? "Temporary" : "", AOTConfiguration);
@@ -1044,11 +1065,10 @@ bool MetaspaceShared::write_static_archive(ArchiveBuilder* builder, FileMapInfo*
// relocate the data so that it can be mapped to MetaspaceShared::requested_base_address()
// without runtime relocation.
builder->relocate_to_requested();
-
- map_info->open_as_output();
if (!map_info->is_open()) {
return false;
}
+ map_info->prepare_for_writing();
builder->write_archive(map_info, heap_info);
if (AllowArchivingWithJavaAgent) {
@@ -1287,6 +1307,10 @@ void MetaspaceShared::report_loading_error(const char* format, ...) {
LogStream ls_cds(level, LogTagSetMapping::tagset());
LogStream& ls = CDSConfig::new_aot_flags_used() ? ls_aot : ls_cds;
+ if (!ls.is_enabled()) {
+ return;
+ }
+
va_list ap;
va_start(ap, format);
diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp
index 130e7fe4484..f7746129d16 100644
--- a/src/hotspot/share/cds/metaspaceShared.hpp
+++ b/src/hotspot/share/cds/metaspaceShared.hpp
@@ -59,6 +59,7 @@ class MetaspaceShared : AllStatic {
static char* _requested_base_address;
static bool _use_optimized_module_handling;
static Array* _archived_method_handle_intrinsics;
+ static FileMapInfo* _output_mapinfo;
public:
enum {
@@ -180,6 +181,7 @@ class MetaspaceShared : AllStatic {
private:
static void read_extra_data(JavaThread* current, const char* filename) NOT_CDS_RETURN;
static void fork_and_dump_final_static_archive(TRAPS);
+ static void open_output_mapinfo();
static bool write_static_archive(ArchiveBuilder* builder, FileMapInfo* map_info, ArchiveHeapInfo* heap_info);
static FileMapInfo* open_static_archive();
static FileMapInfo* open_dynamic_archive();
diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp
index f9829e88c4a..72ec2866c6e 100644
--- a/src/hotspot/share/ci/ciReplay.cpp
+++ b/src/hotspot/share/ci/ciReplay.cpp
@@ -802,7 +802,7 @@ class CompileReplay : public StackObj {
// Make sure the existence of a prior compile doesn't stop this one
nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
if (nm != nullptr) {
- nm->make_not_entrant(nmethod::ChangeReason::CI_replay);
+ nm->make_not_entrant(nmethod::InvalidationReason::CI_REPLAY);
}
replay_state = this;
CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level,
diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
index e6c10859371..b8734dcea25 100644
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.cpp
@@ -1192,10 +1192,7 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik,
oop loader = ik->class_loader();
char* src = (char*)stream->source();
if (src == nullptr) {
- if (loader == nullptr) {
- // JFR classes
- ik->set_shared_classpath_index(0);
- }
+ ik->set_shared_classpath_index(-1); // unsupported location
return;
}
diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp
index 03af71bc26f..506f8891043 100644
--- a/src/hotspot/share/classfile/resolutionErrors.cpp
+++ b/src/hotspot/share/classfile/resolutionErrors.cpp
@@ -73,7 +73,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde
ResolutionErrorKey key(pool(), cp_index);
ResolutionErrorEntry *entry = new ResolutionErrorEntry(error, message, cause, cause_msg);
- _resolution_error_table->put(key, entry);
+ _resolution_error_table->put_when_absent(key, entry);
}
// create new nest host error entry
@@ -85,7 +85,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde
ResolutionErrorKey key(pool(), cp_index);
ResolutionErrorEntry *entry = new ResolutionErrorEntry(message);
- _resolution_error_table->put(key, entry);
+ _resolution_error_table->put_when_absent(key, entry);
}
// find entry in the table
@@ -126,6 +126,13 @@ ResolutionErrorEntry::~ResolutionErrorEntry() {
}
}
+void ResolutionErrorEntry::set_nest_host_error(const char* message) {
+ assert(_nest_host_error == nullptr, "caller should have checked");
+ assert_lock_strong(SystemDictionary_lock);
+ _nest_host_error = message;
+}
+
+
class ResolutionErrorDeleteIterate : StackObj {
ConstantPool* p;
diff --git a/src/hotspot/share/classfile/resolutionErrors.hpp b/src/hotspot/share/classfile/resolutionErrors.hpp
index 60f8aea68ef..39859ad2b70 100644
--- a/src/hotspot/share/classfile/resolutionErrors.hpp
+++ b/src/hotspot/share/classfile/resolutionErrors.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -91,10 +91,7 @@ class ResolutionErrorEntry : public CHeapObj {
~ResolutionErrorEntry();
// The incoming nest host error message is already in the C-Heap.
- void set_nest_host_error(const char* message) {
- _nest_host_error = message;
- }
-
+ void set_nest_host_error(const char* message);
Symbol* error() const { return _error; }
const char* message() const { return _message; }
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
index b1abb2ab0fe..ee526e9bb07 100644
--- a/src/hotspot/share/classfile/systemDictionary.cpp
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
@@ -55,6 +55,7 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
+#include "oops/constantPool.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
@@ -1806,18 +1807,28 @@ Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool,
void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool,
int which,
- const char* message) {
+ const stringStream& message) {
{
MutexLocker ml(Thread::current(), SystemDictionary_lock);
ResolutionErrorEntry* entry = ResolutionErrorTable::find_entry(pool, which);
- if (entry != nullptr && entry->nest_host_error() == nullptr) {
+ if (entry == nullptr) {
+ // Only add a new entry to the resolution error table if one hasn't been found for this
+ // constant pool index. In this case resolution succeeded but there's an error in this nest host
+ // that we use the table to record.
+ assert(pool->resolved_klass_at(which) != nullptr, "klass should be resolved if there is no entry");
+ ResolutionErrorTable::add_entry(pool, which, message.as_string(true /* on C-heap */));
+ } else {
// An existing entry means we had a true resolution failure (LinkageError) with our nest host, but we
// still want to add the error message for the higher-level access checks to report. We should
// only reach here under the same error condition, so we can ignore the potential race with setting
- // the message. If we see it is already set then we can ignore it.
- entry->set_nest_host_error(message);
- } else {
- ResolutionErrorTable::add_entry(pool, which, message);
+ // the message.
+ const char* nhe = entry->nest_host_error();
+ if (nhe == nullptr) {
+ entry->set_nest_host_error(message.as_string(true /* on C-heap */));
+ } else {
+ DEBUG_ONLY(const char* msg = message.base();)
+ assert(strcmp(nhe, msg) == 0, "New message %s, differs from original %s", msg, nhe);
+ }
}
}
}
diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp
index 8cf2cd83b82..b8efef8edcb 100644
--- a/src/hotspot/share/classfile/systemDictionary.hpp
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
@@ -280,7 +280,7 @@ class SystemDictionary : AllStatic {
// Record a nest host resolution/validation error
static void add_nest_host_error(const constantPoolHandle& pool, int which,
- const char* message);
+ const stringStream& message);
static const char* find_nest_host_error(const constantPoolHandle& pool, int which);
static void add_to_initiating_loader(JavaThread* current, InstanceKlass* k,
diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp
index cf21f1f89a4..96b9d8c0e0d 100644
--- a/src/hotspot/share/code/codeBlob.cpp
+++ b/src/hotspot/share/code/codeBlob.cpp
@@ -897,6 +897,7 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const
nm->print_nmethod(true);
} else {
nm->print_on(st);
+ nm->print_code_snippet(st, addr);
}
return;
}
diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp
index ce8f81bfa7b..169e938fd9d 100644
--- a/src/hotspot/share/code/codeCache.cpp
+++ b/src/hotspot/share/code/codeCache.cpp
@@ -227,11 +227,6 @@ void CodeCache::initialize_heaps() {
if (!non_nmethod.set) {
non_nmethod.size += compiler_buffer_size;
- // Further down, just before FLAG_SET_ERGO(), all segment sizes are
- // aligned down to the next lower multiple of min_size. For large page
- // sizes, this may result in (non_nmethod.size == 0) which is not acceptable.
- // Therefore, force non_nmethod.size to at least min_size.
- non_nmethod.size = MAX2(non_nmethod.size, min_size);
}
if (!profiled.set && !non_profiled.set) {
@@ -307,11 +302,10 @@ void CodeCache::initialize_heaps() {
// Note: if large page support is enabled, min_size is at least the large
// page size. This ensures that the code cache is covered by large pages.
- non_profiled.size += non_nmethod.size & alignment_mask(min_size);
- non_profiled.size += profiled.size & alignment_mask(min_size);
- non_nmethod.size = align_down(non_nmethod.size, min_size);
- profiled.size = align_down(profiled.size, min_size);
- non_profiled.size = align_down(non_profiled.size, min_size);
+ non_nmethod.size = align_up(non_nmethod.size, min_size);
+ profiled.size = align_up(profiled.size, min_size);
+ non_profiled.size = align_up(non_profiled.size, min_size);
+ cache_size = non_nmethod.size + profiled.size + non_profiled.size;
FLAG_SET_ERGO(NonNMethodCodeHeapSize, non_nmethod.size);
FLAG_SET_ERGO(ProfiledCodeHeapSize, profiled.size);
@@ -1362,7 +1356,7 @@ void CodeCache::make_marked_nmethods_deoptimized() {
while(iter.next()) {
nmethod* nm = iter.method();
if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) {
- nm->make_not_entrant(nmethod::ChangeReason::marked_for_deoptimization);
+ nm->make_not_entrant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION);
nm->make_deoptimized();
}
}
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index e4721485e8d..4d39b715f25 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -1970,12 +1970,12 @@ void nmethod::invalidate_osr_method() {
}
}
-void nmethod::log_state_change(ChangeReason change_reason) const {
+void nmethod::log_state_change(InvalidationReason invalidation_reason) const {
if (LogCompilation) {
if (xtty != nullptr) {
ttyLocker ttyl; // keep the following output all in one block
xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'",
- os::current_thread_id(), change_reason_to_string(change_reason));
+ os::current_thread_id(), invalidation_reason_to_string(invalidation_reason));
log_identity(xtty);
xtty->stamp();
xtty->end_elem();
@@ -1984,7 +1984,7 @@ void nmethod::log_state_change(ChangeReason change_reason) const {
ResourceMark rm;
stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256);
- ss.print("made not entrant: %s", change_reason_to_string(change_reason));
+ ss.print("made not entrant: %s", invalidation_reason_to_string(invalidation_reason));
CompileTask::print_ul(this, ss.freeze());
if (PrintCompilation) {
@@ -1999,7 +1999,7 @@ void nmethod::unlink_from_method() {
}
// Invalidate code
-bool nmethod::make_not_entrant(ChangeReason change_reason) {
+bool nmethod::make_not_entrant(InvalidationReason invalidation_reason) {
// This can be called while the system is already at a safepoint which is ok
NoSafepointVerifier nsv;
@@ -2057,7 +2057,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) {
assert(success, "Transition can't fail");
// Log the transition once
- log_state_change(change_reason);
+ log_state_change(invalidation_reason);
// Remove nmethod from method.
unlink_from_method();
@@ -2068,7 +2068,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) {
// Invalidate can't occur while holding the NMethodState_lock
JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
if (nmethod_data != nullptr) {
- nmethod_data->invalidate_nmethod_mirror(this);
+ nmethod_data->invalidate_nmethod_mirror(this, invalidation_reason);
}
#endif
@@ -2106,7 +2106,9 @@ void nmethod::unlink() {
// Clear the link between this nmethod and a HotSpotNmethod mirror
JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
if (nmethod_data != nullptr) {
- nmethod_data->invalidate_nmethod_mirror(this);
+ nmethod_data->invalidate_nmethod_mirror(this, is_cold() ?
+ nmethod::InvalidationReason::UNLOADING_COLD :
+ nmethod::InvalidationReason::UNLOADING);
}
#endif
@@ -3999,6 +4001,46 @@ void nmethod::print_value_on_impl(outputStream* st) const {
#endif
}
+void nmethod::print_code_snippet(outputStream* st, address addr) const {
+ if (entry_point() <= addr && addr < code_end()) {
+ // Pointing into the nmethod's code. Try to disassemble some instructions around addr.
+ // Determine conservative start and end points.
+ address start;
+ if (frame_complete_offset() != CodeOffsets::frame_never_safe &&
+ addr >= code_begin() + frame_complete_offset()) {
+ start = code_begin() + frame_complete_offset();
+ } else {
+ start = (addr < verified_entry_point()) ? entry_point() : verified_entry_point();
+ }
+ address start_for_hex_dump = start; // We can choose a different starting point for hex dump, below.
+ address end = code_end();
+
+ // Try using relocations to find closer instruction start and end points.
+ // (Some platforms have variable length instructions and can only
+ // disassemble correctly at instruction start addresses.)
+ RelocIterator iter((nmethod*)this, start);
+ while (iter.next() && iter.addr() < addr) { // find relocation before addr
+ // Note: There's a relocation which doesn't point to an instruction start:
+ // ZBarrierRelocationFormatStoreGoodAfterMov with ZGC on x86_64
+ // We could detect and skip it, but hex dump is still usable when
+ // disassembler produces garbage in such a very rare case.
+ start = iter.addr();
+ // We want at least 64 Bytes ahead in hex dump.
+ if (iter.addr() <= (addr - 64)) start_for_hex_dump = iter.addr();
+ }
+ if (iter.has_current()) {
+ if (iter.addr() == addr) iter.next(); // find relocation after addr
+ if (iter.has_current()) end = iter.addr();
+ }
+
+ // Always print hex. Disassembler may still have problems when hitting an incorrect instruction start.
+ os::print_hex_dump(st, start_for_hex_dump, end, 1, /* print_ascii=*/false);
+ if (!Disassembler::is_abstract()) {
+ Disassembler::decode(start, end, st);
+ }
+ }
+}
+
#ifndef PRODUCT
void nmethod::print_calls(outputStream* st) {
diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp
index 7453bdfa0ef..35adb84733a 100644
--- a/src/hotspot/share/code/nmethod.hpp
+++ b/src/hotspot/share/code/nmethod.hpp
@@ -471,77 +471,74 @@ class nmethod : public CodeBlob {
void oops_do_set_strong_done(nmethod* old_head);
public:
- enum class ChangeReason : u1 {
- C1_codepatch,
- C1_deoptimize,
- C1_deoptimize_for_patching,
- C1_predicate_failed_trap,
- CI_replay,
- JVMCI_invalidate_nmethod,
- JVMCI_invalidate_nmethod_mirror,
- JVMCI_materialize_virtual_object,
- JVMCI_new_installation,
- JVMCI_register_method,
- JVMCI_replacing_with_new_code,
- JVMCI_reprofile,
- marked_for_deoptimization,
- missing_exception_handler,
- not_used,
- OSR_invalidation_back_branch,
- OSR_invalidation_for_compiling_with_C1,
- OSR_invalidation_of_lower_level,
- set_native_function,
- uncommon_trap,
- whitebox_deoptimization,
- zombie,
+ // If you change anything in this enum please patch
+ // vmStructs_jvmci.cpp accordingly.
+ enum class InvalidationReason : s1 {
+ NOT_INVALIDATED = -1,
+ C1_CODEPATCH,
+ C1_DEOPTIMIZE,
+ C1_DEOPTIMIZE_FOR_PATCHING,
+ C1_PREDICATE_FAILED_TRAP,
+ CI_REPLAY,
+ UNLOADING,
+ UNLOADING_COLD,
+ JVMCI_INVALIDATE,
+ JVMCI_MATERIALIZE_VIRTUAL_OBJECT,
+ JVMCI_REPLACED_WITH_NEW_CODE,
+ JVMCI_REPROFILE,
+ MARKED_FOR_DEOPTIMIZATION,
+ MISSING_EXCEPTION_HANDLER,
+ NOT_USED,
+ OSR_INVALIDATION_BACK_BRANCH,
+ OSR_INVALIDATION_FOR_COMPILING_WITH_C1,
+ OSR_INVALIDATION_OF_LOWER_LEVEL,
+ SET_NATIVE_FUNCTION,
+ UNCOMMON_TRAP,
+ WHITEBOX_DEOPTIMIZATION,
+ ZOMBIE,
+ INVALIDATION_REASONS_COUNT
};
- static const char* change_reason_to_string(ChangeReason change_reason) {
- switch (change_reason) {
- case ChangeReason::C1_codepatch:
+ static const char* invalidation_reason_to_string(InvalidationReason invalidation_reason) {
+ switch (invalidation_reason) {
+ case InvalidationReason::C1_CODEPATCH:
return "C1 code patch";
- case ChangeReason::C1_deoptimize:
+ case InvalidationReason::C1_DEOPTIMIZE:
return "C1 deoptimized";
- case ChangeReason::C1_deoptimize_for_patching:
+ case InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING:
return "C1 deoptimize for patching";
- case ChangeReason::C1_predicate_failed_trap:
+ case InvalidationReason::C1_PREDICATE_FAILED_TRAP:
return "C1 predicate failed trap";
- case ChangeReason::CI_replay:
+ case InvalidationReason::CI_REPLAY:
return "CI replay";
- case ChangeReason::JVMCI_invalidate_nmethod:
- return "JVMCI invalidate nmethod";
- case ChangeReason::JVMCI_invalidate_nmethod_mirror:
- return "JVMCI invalidate nmethod mirror";
- case ChangeReason::JVMCI_materialize_virtual_object:
+ case InvalidationReason::JVMCI_INVALIDATE:
+ return "JVMCI invalidate";
+ case InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT:
return "JVMCI materialize virtual object";
- case ChangeReason::JVMCI_new_installation:
- return "JVMCI new installation";
- case ChangeReason::JVMCI_register_method:
- return "JVMCI register method";
- case ChangeReason::JVMCI_replacing_with_new_code:
- return "JVMCI replacing with new code";
- case ChangeReason::JVMCI_reprofile:
+ case InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE:
+ return "JVMCI replaced with new code";
+ case InvalidationReason::JVMCI_REPROFILE:
return "JVMCI reprofile";
- case ChangeReason::marked_for_deoptimization:
+ case InvalidationReason::MARKED_FOR_DEOPTIMIZATION:
return "marked for deoptimization";
- case ChangeReason::missing_exception_handler:
+ case InvalidationReason::MISSING_EXCEPTION_HANDLER:
return "missing exception handler";
- case ChangeReason::not_used:
+ case InvalidationReason::NOT_USED:
return "not used";
- case ChangeReason::OSR_invalidation_back_branch:
+ case InvalidationReason::OSR_INVALIDATION_BACK_BRANCH:
return "OSR invalidation back branch";
- case ChangeReason::OSR_invalidation_for_compiling_with_C1:
+ case InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1:
return "OSR invalidation for compiling with C1";
- case ChangeReason::OSR_invalidation_of_lower_level:
+ case InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL:
return "OSR invalidation of lower level";
- case ChangeReason::set_native_function:
+ case InvalidationReason::SET_NATIVE_FUNCTION:
return "set native function";
- case ChangeReason::uncommon_trap:
+ case InvalidationReason::UNCOMMON_TRAP:
return "uncommon trap";
- case ChangeReason::whitebox_deoptimization:
+ case InvalidationReason::WHITEBOX_DEOPTIMIZATION:
return "whitebox deoptimization";
- case ChangeReason::zombie:
+ case InvalidationReason::ZOMBIE:
return "zombie";
default: {
assert(false, "Unhandled reason");
@@ -712,8 +709,8 @@ class nmethod : public CodeBlob {
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
- bool make_not_entrant(ChangeReason change_reason);
- bool make_not_used() { return make_not_entrant(ChangeReason::not_used); }
+ bool make_not_entrant(InvalidationReason invalidation_reason);
+ bool make_not_used() { return make_not_entrant(InvalidationReason::NOT_USED); }
bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; }
bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; }
@@ -996,6 +993,7 @@ class nmethod : public CodeBlob {
void print_on_impl(outputStream* st) const;
void print_code();
void print_value_on_impl(outputStream* st) const;
+ void print_code_snippet(outputStream* st, address addr) const;
#if defined(SUPPORT_DATA_STRUCTS)
// print output in opt build for disassembler library
@@ -1026,7 +1024,7 @@ class nmethod : public CodeBlob {
// Logging
void log_identity(xmlStream* log) const;
void log_new_nmethod() const;
- void log_state_change(ChangeReason change_reason) const;
+ void log_state_change(InvalidationReason invalidation_reason) const;
// Prints block-level comments, including nmethod specific block labels:
void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const;
diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp
index 658786d1cdb..6f84dbeb40c 100644
--- a/src/hotspot/share/compiler/compilationPolicy.cpp
+++ b/src/hotspot/share/compiler/compilationPolicy.cpp
@@ -931,7 +931,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level
nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false);
if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) {
// Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted.
- osr_nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_for_compiling_with_C1);
+ osr_nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1);
}
compile(mh, bci, CompLevel_simple, THREAD);
}
@@ -1529,7 +1529,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m
int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
}
- nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_back_branch);
+ nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH);
}
}
// Fix up next_level if necessary to avoid deopts
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index 27ca7611252..e96fbeba964 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -28,6 +28,7 @@
#include "code/codeCache.hpp"
#include "compiler/oopMap.hpp"
#include "gc/g1/g1Allocator.inline.hpp"
+#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/g1Arguments.hpp"
#include "gc/g1/g1BarrierSet.hpp"
#include "gc/g1/g1BatchedTask.hpp"
@@ -387,22 +388,26 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t min_size,
assert_heap_not_locked_and_not_at_safepoint();
assert(!is_humongous(requested_size), "we do not allow humongous TLABs");
- return attempt_allocation(min_size, requested_size, actual_size);
+ // Do not allow a GC because we are allocating a new TLAB to avoid an issue
+ // with UseGCOverheadLimit: although this GC would return null if the overhead
+ // limit would be exceeded, but it would likely free at least some space.
+ // So the subsequent outside-TLAB allocation could be successful anyway and
+ // the indication that the overhead limit had been exceeded swallowed.
+ return attempt_allocation(min_size, requested_size, actual_size, false /* allow_gc */);
}
-HeapWord*
-G1CollectedHeap::mem_allocate(size_t word_size,
- bool* gc_overhead_limit_was_exceeded) {
+HeapWord* G1CollectedHeap::mem_allocate(size_t word_size,
+ bool* gc_overhead_limit_was_exceeded) {
assert_heap_not_locked_and_not_at_safepoint();
if (is_humongous(word_size)) {
return attempt_allocation_humongous(word_size);
}
size_t dummy = 0;
- return attempt_allocation(word_size, word_size, &dummy);
+ return attempt_allocation(word_size, word_size, &dummy, true /* allow_gc */);
}
-HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size) {
+HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc) {
ResourceMark rm; // For retrieving the thread names in log messages.
// Make sure you read the note in attempt_allocation_humongous().
@@ -429,6 +434,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_
result = _allocator->attempt_allocation_locked(node_index, word_size);
if (result != nullptr) {
return result;
+ } else if (!allow_gc) {
+ return nullptr;
}
// Read the GC count while still holding the Heap_lock.
@@ -446,8 +453,15 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating %zu words",
Thread::current()->name(), word_size);
+ // Has the gc overhead limit been reached in the meantime? If so, this mutator
+ // should receive null even when unsuccessfully scheduling a collection as well
+ // for global consistency.
+ if (gc_overhead_limit_exceeded()) {
+ return nullptr;
+ }
+
// We can reach here if we were unsuccessful in scheduling a collection (because
- // another thread beat us to it). In this case immeditealy retry the allocation
+ // another thread beat us to it). In this case immediately retry the allocation
// attempt because another thread successfully performed a collection and possibly
// reclaimed enough space. The first attempt (without holding the Heap_lock) is
// here and the follow-on attempt will be at the start of the next loop
@@ -592,7 +606,8 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion range) {
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size,
size_t desired_word_size,
- size_t* actual_word_size) {
+ size_t* actual_word_size,
+ bool allow_gc) {
assert_heap_not_locked_and_not_at_safepoint();
assert(!is_humongous(desired_word_size), "attempt_allocation() should not "
"be called for humongous allocation requests");
@@ -604,7 +619,7 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size,
if (result == nullptr) {
*actual_word_size = desired_word_size;
- result = attempt_allocation_slow(node_index, desired_word_size);
+ result = attempt_allocation_slow(node_index, desired_word_size, allow_gc);
}
assert_heap_not_locked();
@@ -688,6 +703,13 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) {
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating %zu",
Thread::current()->name(), word_size);
+ // Has the gc overhead limit been reached in the meantime? If so, this mutator
+ // should receive null even when unsuccessfully scheduling a collection as well
+ // for global consistency.
+ if (gc_overhead_limit_exceeded()) {
+ return nullptr;
+ }
+
// We can reach here if we were unsuccessful in scheduling a collection (because
// another thread beat us to it).
// Humongous object allocation always needs a lock, so we wait for the retry
@@ -890,25 +912,62 @@ void G1CollectedHeap::resize_heap_if_necessary(size_t allocation_word_size) {
}
}
+void G1CollectedHeap::update_gc_overhead_counter() {
+ assert(SafepointSynchronize::is_at_safepoint(), "precondition");
+
+ if (!UseGCOverheadLimit) {
+ return;
+ }
+
+ bool gc_time_over_limit = (_policy->analytics()->long_term_pause_time_ratio() * 100) >= GCTimeLimit;
+ double free_space_percent = percent_of(num_available_regions() * G1HeapRegion::GrainBytes, max_capacity());
+ bool free_space_below_limit = free_space_percent < GCHeapFreeLimit;
+
+ log_debug(gc)("GC Overhead Limit: GC Time %f Free Space %f Counter %zu",
+ (_policy->analytics()->long_term_pause_time_ratio() * 100),
+ free_space_percent,
+ _gc_overhead_counter);
+
+ if (gc_time_over_limit && free_space_below_limit) {
+ _gc_overhead_counter++;
+ } else {
+ _gc_overhead_counter = 0;
+ }
+}
+
+bool G1CollectedHeap::gc_overhead_limit_exceeded() {
+ return _gc_overhead_counter >= GCOverheadLimitThreshold;
+}
+
HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
bool do_gc,
bool maximal_compaction,
bool expect_null_mutator_alloc_region) {
- // Let's attempt the allocation first.
- HeapWord* result =
- attempt_allocation_at_safepoint(word_size,
- expect_null_mutator_alloc_region);
- if (result != nullptr) {
- return result;
- }
+ // Skip allocation if GC overhead limit has been exceeded to let the mutator run
+ // into an OOME. It can either exit "gracefully" or try to free up memory asap.
+ // For the latter situation, keep running GCs. If the mutator frees up enough
+ // memory quickly enough, the overhead(s) will go below the threshold(s) again
+ // and the VM may continue running.
+ // If we did not continue garbage collections, the (gc overhead) limit may decrease
+ // enough by itself to not count as exceeding the limit any more, in the worst
+ // case bouncing back-and-forth all the time.
+ if (!gc_overhead_limit_exceeded()) {
+ // Let's attempt the allocation first.
+ HeapWord* result =
+ attempt_allocation_at_safepoint(word_size,
+ expect_null_mutator_alloc_region);
+ if (result != nullptr) {
+ return result;
+ }
- // In a G1 heap, we're supposed to keep allocation from failing by
- // incremental pauses. Therefore, at least for now, we'll favor
- // expansion over collection. (This might change in the future if we can
- // do something smarter than full collection to satisfy a failed alloc.)
- result = expand_and_allocate(word_size);
- if (result != nullptr) {
- return result;
+ // In a G1 heap, we're supposed to keep allocation from failing by
+ // incremental pauses. Therefore, at least for now, we'll favor
+ // expansion over collection. (This might change in the future if we can
+ // do something smarter than full collection to satisfy a failed alloc.)
+ result = expand_and_allocate(word_size);
+ if (result != nullptr) {
+ return result;
+ }
}
if (do_gc) {
@@ -932,6 +991,10 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
assert_at_safepoint_on_vm_thread();
+ // Update GC overhead limits after the initial garbage collection leading to this
+ // allocation attempt.
+ update_gc_overhead_counter();
+
// Attempts to allocate followed by Full GC.
HeapWord* result =
satisfy_failed_allocation_helper(word_size,
@@ -966,6 +1029,10 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
assert(!soft_ref_policy()->should_clear_all_soft_refs(),
"Flag should have been handled and cleared prior to this point");
+ if (gc_overhead_limit_exceeded()) {
+ log_info(gc)("GC Overhead Limit exceeded too often (%zu).", GCOverheadLimitThreshold);
+ }
+
// What else? We might try synchronous finalization later. If the total
// space available is large enough for the allocation, then a more
// complete compaction phase than we've tried so far might be
@@ -1131,6 +1198,7 @@ class HumongousRegionSetChecker : public G1HeapRegionSetChecker {
G1CollectedHeap::G1CollectedHeap() :
CollectedHeap(),
+ _gc_overhead_counter(0),
_service_thread(nullptr),
_periodic_gc_task(nullptr),
_free_arena_memory_task(nullptr),
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp
index a00edd326f5..c74d77aefce 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp
@@ -169,6 +169,17 @@ class G1CollectedHeap : public CollectedHeap {
friend class G1CheckRegionAttrTableClosure;
private:
+ // GC Overhead Limit functionality related members.
+ //
+ // The goal is to return null for allocations prematurely (before really going
+ // OOME) in case both GC CPU usage (>= GCTimeLimit) and not much available free
+ // memory (<= GCHeapFreeLimit) so that applications can exit gracefully or try
+ // to keep running by easing off memory.
+ uintx _gc_overhead_counter; // The number of consecutive garbage collections we were over the limits.
+
+ void update_gc_overhead_counter();
+ bool gc_overhead_limit_exceeded();
+
G1ServiceThread* _service_thread;
G1ServiceTask* _periodic_gc_task;
G1MonotonicArenaFreeMemoryTask* _free_arena_memory_task;
@@ -425,18 +436,14 @@ class G1CollectedHeap : public CollectedHeap {
//
// * If either call cannot satisfy the allocation request using the
// current allocating region, they will try to get a new one. If
- // this fails, they will attempt to do an evacuation pause and
- // retry the allocation.
- //
- // * If all allocation attempts fail, even after trying to schedule
- // an evacuation pause, allocate_new_tlab() will return null,
- // whereas mem_allocate() will attempt a heap expansion and/or
- // schedule a Full GC.
+ // this fails, (only) mem_allocate() will attempt to do an evacuation
+ // pause and retry the allocation. Allocate_new_tlab() will return null,
+ // deferring to the following mem_allocate().
//
// * We do not allow humongous-sized TLABs. So, allocate_new_tlab
// should never be called with word_size being humongous. All
// humongous allocation requests should go to mem_allocate() which
- // will satisfy them with a special path.
+ // will satisfy them in a special path.
HeapWord* allocate_new_tlab(size_t min_size,
size_t requested_size,
@@ -450,12 +457,13 @@ class G1CollectedHeap : public CollectedHeap {
// should only be used for non-humongous allocations.
inline HeapWord* attempt_allocation(size_t min_word_size,
size_t desired_word_size,
- size_t* actual_word_size);
-
+ size_t* actual_word_size,
+ bool allow_gc);
// Second-level mutator allocation attempt: take the Heap_lock and
// retry the allocation attempt, potentially scheduling a GC
- // pause. This should only be used for non-humongous allocations.
- HeapWord* attempt_allocation_slow(uint node_index, size_t word_size);
+ // pause if allow_gc is set. This should only be used for non-humongous
+ // allocations.
+ HeapWord* attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc);
// Takes the Heap_lock and attempts a humongous allocation. It can
// potentially schedule a GC pause.
diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
index f7b0cb23b65..18e0e40c54a 100644
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
@@ -570,8 +570,8 @@ void G1GCPhaseTimes::print(bool evacuation_failed) {
accounted_ms += print_evacuate_optional_collection_set();
accounted_ms += print_post_evacuate_collection_set(evacuation_failed);
- assert(_gc_pause_time_ms >= accounted_ms, "GC pause time(%.3lfms) cannot be "
- "smaller than the sum of each phase(%.3lfms).", _gc_pause_time_ms, accounted_ms);
+ assert(_gc_pause_time_ms >= accounted_ms, "GC pause time(%.15lf ms) cannot be "
+ "smaller than the sum of each phase(%.15lf ms).", _gc_pause_time_ms, accounted_ms);
print_other(accounted_ms);
diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp
index 2d23dce9488..5e83c8b76d8 100644
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp
@@ -67,7 +67,7 @@ Klass* CollectedHeap::_filler_object_klass = nullptr;
size_t CollectedHeap::_filler_array_max_size = 0;
size_t CollectedHeap::_stack_chunk_max_size = 0;
-class GCLogMessage : public FormatBuffer<512> {};
+class GCLogMessage : public FormatBuffer<1024> {};
template <>
void EventLogBase::print(outputStream* st, GCLogMessage& m) {
diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp
index f693ab910ba..4b3cbf04b40 100644
--- a/src/hotspot/share/gc/shared/gc_globals.hpp
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp
@@ -414,7 +414,7 @@
"Initial ratio of young generation/survivor space size") \
range(3, max_uintx) \
\
- product(bool, UseGCOverheadLimit, true, \
+ product(bool, UseGCOverheadLimit, falseInDebug, \
"Use policy to limit of proportion of time spent in GC " \
"before an OutOfMemory error is thrown") \
\
diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp
index 28e5e9adf20..9da11518c3e 100644
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp
@@ -100,13 +100,17 @@ void StringDedup::Stat::log_summary(const Stat* last_stat, const Stat* total_sta
log_info(stringdedup)(
"Concurrent String Deduplication "
- "%zu/" STRDEDUP_BYTES_FORMAT_NS " (new), "
+ "%zu (inspected), "
+ "%zu/" STRDEDUP_BYTES_FORMAT_NS " (new unknown), "
"%zu/" STRDEDUP_BYTES_FORMAT_NS " (deduped), "
- "avg " STRDEDUP_PERCENT_FORMAT_NS ", "
+ "total avg deduped/new unknown bytes " STRDEDUP_PERCENT_FORMAT_NS ", "
+ STRDEDUP_BYTES_FORMAT_NS " (total deduped)," STRDEDUP_BYTES_FORMAT_NS " (total new unknown), "
STRDEDUP_ELAPSED_FORMAT_MS " of " STRDEDUP_ELAPSED_FORMAT_MS,
+ last_stat->_inspected,
last_stat->_new, STRDEDUP_BYTES_PARAM(last_stat->_new_bytes),
last_stat->_deduped, STRDEDUP_BYTES_PARAM(last_stat->_deduped_bytes),
total_deduped_bytes_percent,
+ STRDEDUP_BYTES_PARAM(total_stat->_deduped_bytes), STRDEDUP_BYTES_PARAM(total_stat->_new_bytes),
strdedup_elapsed_param_ms(last_stat->_process_elapsed),
strdedup_elapsed_param_ms(last_stat->_active_elapsed));
}
@@ -217,14 +221,14 @@ void StringDedup::Stat::log_statistics(bool total) const {
double replaced_percent = percent_of(_replaced, _new);
double deleted_percent = percent_of(_deleted, _new);
log_times(total ? "Total" : "Last");
- log_debug(stringdedup)(" Inspected: %12zu", _inspected);
- log_debug(stringdedup)(" Known: %12zu(%5.1f%%)", _known, known_percent);
- log_debug(stringdedup)(" Shared: %12zu(%5.1f%%)", _known_shared, known_shared_percent);
- log_debug(stringdedup)(" New: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT,
+ log_debug(stringdedup)(" Inspected: %12zu", _inspected);
+ log_debug(stringdedup)(" Known: %12zu(%5.1f%%)", _known, known_percent);
+ log_debug(stringdedup)(" Shared: %12zu(%5.1f%%)", _known_shared, known_shared_percent);
+ log_debug(stringdedup)(" New unknown: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT,
_new, new_percent, STRDEDUP_BYTES_PARAM(_new_bytes));
- log_debug(stringdedup)(" Replaced: %12zu(%5.1f%%)", _replaced, replaced_percent);
- log_debug(stringdedup)(" Deleted: %12zu(%5.1f%%)", _deleted, deleted_percent);
- log_debug(stringdedup)(" Deduplicated: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT "(%5.1f%%)",
+ log_debug(stringdedup)(" Replaced: %12zu(%5.1f%%)", _replaced, replaced_percent);
+ log_debug(stringdedup)(" Deleted: %12zu(%5.1f%%)", _deleted, deleted_percent);
+ log_debug(stringdedup)(" Deduplicated: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT "(%5.1f%%)",
_deduped, deduped_percent, STRDEDUP_BYTES_PARAM(_deduped_bytes), deduped_bytes_percent);
log_debug(stringdedup)(" Skipped: %zu (dead), %zu (incomplete), %zu (shared)",
_skipped_dead, _skipped_incomplete, _skipped_shared);
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
index eb87a9dc4c1..3ec42478282 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
@@ -91,7 +91,7 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand
// we hit max_cset. When max_cset is hit, we terminate the cset selection. Note that in this scheme,
// ShenandoahGarbageThreshold is the soft threshold which would be ignored until min_garbage is hit.
- size_t capacity = _space_info->soft_max_capacity();
+ size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste);
size_t free_target = (capacity / 100 * ShenandoahMinFreeThreshold) + max_cset;
size_t min_garbage = (free_target > actual_free ? (free_target - actual_free) : 0);
@@ -233,7 +233,7 @@ static double saturate(double value, double min, double max) {
// in operation mode. We want some way to decide that the average rate has changed, while keeping average
// allocation rate computation independent.
bool ShenandoahAdaptiveHeuristics::should_start_gc() {
- size_t capacity = _space_info->soft_max_capacity();
+ size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
size_t available = _space_info->soft_available();
size_t allocated = _space_info->bytes_allocated_since_gc_start();
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
index 403405b984d..592bba67757 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
@@ -47,7 +47,7 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp
bool ShenandoahCompactHeuristics::should_start_gc() {
size_t max_capacity = _space_info->max_capacity();
- size_t capacity = _space_info->soft_max_capacity();
+ size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
size_t available = _space_info->available();
// Make sure the code below treats available without the soft tail.
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
index 29b94e2f68f..2131f95b413 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
@@ -37,7 +37,6 @@
class ShenandoahSpaceInfo {
public:
virtual const char* name() const = 0;
- virtual size_t soft_max_capacity() const = 0;
virtual size_t max_capacity() const = 0;
virtual size_t soft_available() const = 0;
virtual size_t available() const = 0;
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp
index e6f60dc1c83..205135751aa 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp
@@ -42,7 +42,7 @@ ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {}
bool ShenandoahStaticHeuristics::should_start_gc() {
size_t max_capacity = _space_info->max_capacity();
- size_t capacity = _space_info->soft_max_capacity();
+ size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
size_t available = _space_info->available();
// Make sure the code below treats available without the soft tail.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
index ffafcc5840d..c23f30a55e9 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
@@ -64,7 +64,9 @@ void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) {
ShenandoahMarkingContext* const ctx = heap->marking_context();
- msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj->klass()), obj->klass()->external_name());
+ Klass* obj_klass = ShenandoahForwarding::klass(obj);
+
+ msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj_klass), obj_klass->external_name());
msg.append(" %3s allocated after mark start\n", ctx->allocated_after_mark_start(obj) ? "" : "not");
msg.append(" %3s after update watermark\n", cast_from_oop(obj) >= r->get_update_watermark() ? "" : "not");
msg.append(" %3s marked strong\n", ctx->is_marked_strong(obj) ? "" : "not");
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
index 37c6a47b1ac..7b3839dc198 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
@@ -182,7 +182,7 @@ void ShenandoahGeneration::log_status(const char *msg) const {
// byte size in proper unit and proper unit for byte size are consistent.
const size_t v_used = used();
const size_t v_used_regions = used_regions_size();
- const size_t v_soft_max_capacity = soft_max_capacity();
+ const size_t v_soft_max_capacity = ShenandoahHeap::heap()->soft_max_capacity();
const size_t v_max_capacity = max_capacity();
const size_t v_available = available();
const size_t v_humongous_waste = get_humongous_waste();
@@ -797,14 +797,13 @@ void ShenandoahGeneration::cancel_marking() {
ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type,
uint max_workers,
- size_t max_capacity,
- size_t soft_max_capacity) :
+ size_t max_capacity) :
_type(type),
_task_queues(new ShenandoahObjToScanQueueSet(max_workers)),
_ref_processor(new ShenandoahReferenceProcessor(MAX2(max_workers, 1U))),
_affiliated_region_count(0), _humongous_waste(0), _evacuation_reserve(0),
_used(0), _bytes_allocated_since_gc_start(0),
- _max_capacity(max_capacity), _soft_max_capacity(soft_max_capacity),
+ _max_capacity(max_capacity),
_heuristics(nullptr)
{
_is_marking_complete.set();
@@ -950,7 +949,7 @@ size_t ShenandoahGeneration::available_with_reserve() const {
}
size_t ShenandoahGeneration::soft_available() const {
- return available(soft_max_capacity());
+ return available(ShenandoahHeap::heap()->soft_max_capacity());
}
size_t ShenandoahGeneration::available(size_t capacity) const {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
index 242acbdea8c..2b7aca342da 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
@@ -71,7 +71,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo {
volatile size_t _used;
volatile size_t _bytes_allocated_since_gc_start;
size_t _max_capacity;
- size_t _soft_max_capacity;
ShenandoahHeuristics* _heuristics;
@@ -105,8 +104,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo {
public:
ShenandoahGeneration(ShenandoahGenerationType type,
uint max_workers,
- size_t max_capacity,
- size_t soft_max_capacity);
+ size_t max_capacity);
~ShenandoahGeneration();
bool is_young() const { return _type == YOUNG; }
@@ -126,7 +124,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo {
virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode);
- size_t soft_max_capacity() const override { return _soft_max_capacity; }
size_t max_capacity() const override { return _max_capacity; }
virtual size_t used_regions() const;
virtual size_t used_regions_size() const;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
index 1bc9c9274e2..feb82dd0527 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
@@ -53,21 +53,6 @@ class ShenandoahGenerationalInitLogger : public ShenandoahInitLogger {
ShenandoahGenerationalInitLogger logger;
logger.print_all();
}
-
- void print_heap() override {
- ShenandoahInitLogger::print_heap();
-
- ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap();
-
- ShenandoahYoungGeneration* young = heap->young_generation();
- log_info(gc, init)("Young Generation Soft Size: " EXACTFMT, EXACTFMTARGS(young->soft_max_capacity()));
- log_info(gc, init)("Young Generation Max: " EXACTFMT, EXACTFMTARGS(young->max_capacity()));
-
- ShenandoahOldGeneration* old = heap->old_generation();
- log_info(gc, init)("Old Generation Soft Size: " EXACTFMT, EXACTFMTARGS(old->soft_max_capacity()));
- log_info(gc, init)("Old Generation Max: " EXACTFMT, EXACTFMTARGS(old->max_capacity()));
- }
-
protected:
void print_gc_specific() override {
ShenandoahInitLogger::print_gc_specific();
@@ -141,8 +126,8 @@ void ShenandoahGenerationalHeap::initialize_heuristics() {
size_t initial_capacity_old = max_capacity() - max_capacity_young;
size_t max_capacity_old = max_capacity() - initial_capacity_young;
- _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young, initial_capacity_young);
- _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old, initial_capacity_old);
+ _young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young);
+ _old_generation = new ShenandoahOldGeneration(max_workers(), max_capacity_old);
_young_generation->initialize_heuristics(mode());
_old_generation->initialize_heuristics(mode());
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
index c6277e3898e..6099c41f262 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp
@@ -50,10 +50,6 @@ size_t ShenandoahGlobalGeneration::used_regions_size() const {
return ShenandoahHeap::heap()->capacity();
}
-size_t ShenandoahGlobalGeneration::soft_max_capacity() const {
- return ShenandoahHeap::heap()->soft_max_capacity();
-}
-
size_t ShenandoahGlobalGeneration::available() const {
// The collector reserve may eat into what the mutator is allowed to use. Make sure we are looking
// at what is available to the mutator when reporting how much memory is available.
@@ -65,8 +61,8 @@ size_t ShenandoahGlobalGeneration::soft_available() const {
size_t available = this->available();
// Make sure the code below treats available without the soft tail.
- assert(max_capacity() >= soft_max_capacity(), "Max capacity must be greater than soft max capacity.");
- size_t soft_tail = max_capacity() - soft_max_capacity();
+ assert(max_capacity() >= ShenandoahHeap::heap()->soft_max_capacity(), "Max capacity must be greater than soft max capacity.");
+ size_t soft_tail = max_capacity() - ShenandoahHeap::heap()->soft_max_capacity();
return (available > soft_tail) ? (available - soft_tail) : 0;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
index 5857170d4cc..a823784a459 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp
@@ -32,14 +32,13 @@
// A "generation" that represents the whole heap.
class ShenandoahGlobalGeneration : public ShenandoahGeneration {
public:
- ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity, size_t soft_max_capacity)
- : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity, soft_max_capacity) { }
+ ShenandoahGlobalGeneration(bool generational, uint max_queues, size_t max_capacity)
+ : ShenandoahGeneration(generational ? GLOBAL : NON_GEN, max_queues, max_capacity) { }
public:
const char* name() const override;
size_t max_capacity() const override;
- size_t soft_max_capacity() const override;
size_t used_regions() const override;
size_t used_regions_size() const override;
size_t available() const override;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index 27bbe375dd0..a56ada222d7 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -32,6 +32,7 @@
#include "gc/shared/gcArguments.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
+#include "gc/shared/gc_globals.hpp"
#include "gc/shared/locationPrinter.inline.hpp"
#include "gc/shared/memAllocator.hpp"
#include "gc/shared/plab.hpp"
@@ -201,8 +202,7 @@ jint ShenandoahHeap::initialize() {
assert(num_min_regions <= _num_regions, "sanity");
_minimum_size = num_min_regions * reg_size_bytes;
- // Default to max heap size.
- _soft_max_size = _num_regions * reg_size_bytes;
+ _soft_max_size = SoftMaxHeapSize;
_committed = _initial_size;
@@ -524,7 +524,7 @@ void ShenandoahHeap::initialize_mode() {
}
void ShenandoahHeap::initialize_heuristics() {
- _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity(), max_capacity());
+ _global_generation = new ShenandoahGlobalGeneration(mode()->is_generational(), max_workers(), max_capacity());
_global_generation->initialize_heuristics(mode());
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
index acef90d2ea3..509ba1db9c2 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
@@ -293,6 +293,7 @@ class ShenandoahHeap : public CollectedHeap {
public:
inline HeapWord* base() const { return _heap_region.start(); }
+ inline HeapWord* end() const { return _heap_region.end(); }
inline size_t num_regions() const { return _num_regions; }
inline bool is_heap_region_special() { return _heap_region_special; }
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp
index b5e5e6fd698..421c001b510 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp
@@ -43,6 +43,7 @@ void ShenandoahInitLogger::print_heap() {
log_info(gc, init)("Heap Region Count: %zu", ShenandoahHeapRegion::region_count());
log_info(gc, init)("Heap Region Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::region_size_bytes()));
log_info(gc, init)("TLAB Size Max: " EXACTFMT, EXACTFMTARGS(ShenandoahHeapRegion::max_tlab_size_bytes()));
+ log_info(gc, init)("Soft Max Heap Size: " EXACTFMT, EXACTFMTARGS(ShenandoahHeap::heap()->soft_max_capacity()));
}
void ShenandoahInitLogger::print_gc_specific() {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp
index 34e6af41b42..5318f38d8ef 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp
@@ -57,6 +57,26 @@ bool ShenandoahMarkBitMap::is_bitmap_clear_range(const HeapWord* start, const He
return (result == end);
}
+HeapWord* ShenandoahMarkBitMap::get_prev_marked_addr(const HeapWord* limit,
+ const HeapWord* addr) const {
+#ifdef ASSERT
+ ShenandoahHeap* heap = ShenandoahHeap::heap();
+ ShenandoahHeapRegion* r = heap->heap_region_containing(addr);
+ ShenandoahMarkingContext* ctx = heap->marking_context();
+ HeapWord* tams = ctx->top_at_mark_start(r);
+ assert(limit != nullptr, "limit must not be null");
+ assert(limit >= r->bottom(), "limit must be more than bottom");
+ assert(addr <= tams, "addr must be less than TAMS");
+#endif
+
+ // Round addr down to a possible object boundary to be safe.
+ size_t const addr_offset = address_to_index(align_down(addr, HeapWordSize << LogMinObjAlignment));
+ size_t const limit_offset = address_to_index(limit);
+ size_t const last_offset = get_prev_one_offset(limit_offset, addr_offset);
+
+ // cast required to remove const-ness of the value pointed to. We won't modify that object, but my caller might.
+ return (last_offset > addr_offset)? (HeapWord*) addr + 1: index_to_address(last_offset);
+}
HeapWord* ShenandoahMarkBitMap::get_next_marked_addr(const HeapWord* addr,
const HeapWord* limit) const {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp
index 56daf4c5956..4c3177d0e81 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp
@@ -119,9 +119,21 @@ class ShenandoahMarkBitMap {
template
inline idx_t get_next_bit_impl(idx_t l_index, idx_t r_index) const;
- inline idx_t get_next_one_offset (idx_t l_index, idx_t r_index) const;
+ // Helper for get_prev_{zero,one}_bit variants.
+ // - flip designates whether searching for 1s or 0s. Must be one of
+ // find_{zeros,ones}_flip.
+ // - aligned_left is true if l_index is a priori on a bm_word_t boundary.
+ template
+ inline idx_t get_prev_bit_impl(idx_t l_index, idx_t r_index) const;
+
+ // Search for the first marked address in the range [l_index, r_index), or r_index if none found.
+ inline idx_t get_next_one_offset(idx_t l_index, idx_t r_index) const;
- void clear_large_range (idx_t beg, idx_t end);
+ // Search for last one in the range [l_index, r_index). Return r_index if not found.
+ inline idx_t get_prev_one_offset(idx_t l_index, idx_t r_index) const;
+
+ // Clear the strong and weak mark bits for all index positions >= l_index and < r_index.
+ void clear_large_range(idx_t beg, idx_t end);
// Verify bit is less than size().
void verify_index(idx_t bit) const NOT_DEBUG_RETURN;
@@ -162,12 +174,14 @@ class ShenandoahMarkBitMap {
bool is_bitmap_clear_range(const HeapWord* start, const HeapWord* end) const;
- // Return the address corresponding to the next marked bit at or after
- // "addr", and before "limit", if "limit" is non-null. If there is no
- // such bit, returns "limit" if that is non-null, or else "endWord()".
+ // Return the first marked address in the range [addr, limit), or limit if none found.
HeapWord* get_next_marked_addr(const HeapWord* addr,
const HeapWord* limit) const;
+ // Return the last marked address in the range [limit, addr], or addr+1 if none found.
+ HeapWord* get_prev_marked_addr(const HeapWord* limit,
+ const HeapWord* addr) const;
+
bm_word_t inverted_bit_mask_for_range(idx_t beg, idx_t end) const;
void clear_range_within_word (idx_t beg, idx_t end);
void clear_range (idx_t beg, idx_t end);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
index f0a9752b614..21b526f9995 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
@@ -29,6 +29,7 @@
#include "gc/shenandoah/shenandoahMarkBitMap.hpp"
#include "runtime/atomic.hpp"
+#include "utilities/count_leading_zeros.hpp"
#include "utilities/count_trailing_zeros.hpp"
inline size_t ShenandoahMarkBitMap::address_to_index(const HeapWord* addr) const {
@@ -171,10 +172,99 @@ inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_bit_impl(idx_t
return r_index;
}
+template
+inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_prev_bit_impl(idx_t l_index, idx_t r_index) const {
+ STATIC_ASSERT(flip == find_ones_flip || flip == find_zeros_flip);
+ verify_range(l_index, r_index);
+ assert(!aligned_left || is_aligned(l_index, BitsPerWord), "l_index not aligned");
+
+ // The first word often contains an interesting bit, either due to
+ // density or because of features of the calling algorithm. So it's
+ // important to examine that first word with a minimum of fuss,
+ // minimizing setup time for later words that will be wasted if the
+ // first word is indeed interesting.
+
+ // The benefit from aligned_left being true is relatively small.
+ // It saves an operation in the setup for the word search loop.
+ // It also eliminates the range check on the final result.
+ // However, callers often have a comparison with l_index, and
+ // inlining often allows the two comparisons to be combined; it is
+ // important when !aligned_left that return paths either return
+ // l_index or a value dominating a comparison with l_index.
+ // aligned_left is still helpful when the caller doesn't have a
+ // range check because features of the calling algorithm guarantee
+ // an interesting bit will be present.
+
+ if (l_index < r_index) {
+ // Get the word containing r_index, and shift out the high-order bits (representing objects that come after r_index)
+ idx_t index = to_words_align_down(r_index);
+ assert(BitsPerWord - 2 >= bit_in_word(r_index), "sanity");
+ size_t shift = BitsPerWord - 2 - bit_in_word(r_index);
+ bm_word_t cword = (map(index) ^ flip) << shift;
+ // After this shift, the highest order bits correspond to r_index.
+
+ // We give special handling if either of the two most significant bits (Weak or Strong) is set. With 64-bit
+ // words, the mask of interest is 0xc000_0000_0000_0000. Symbolically, this constant is represented by:
+ const bm_word_t first_object_mask = ((bm_word_t) 0x3) << (BitsPerWord - 2);
+ if ((cword & first_object_mask) != 0) {
+ // The first object is similarly often interesting. When it matters
+ // (density or features of the calling algorithm make it likely
+ // the first bit is set), going straight to the next clause compares
+ // poorly with doing this check first; count_leading_zeros can be
+ // relatively expensive, plus there is the additional range check.
+ // But when the first bit isn't set, the cost of having tested for
+ // it is relatively small compared to the rest of the search.
+ return r_index;
+ } else if (cword != 0) {
+ // Note that there are 2 bits corresponding to every index value (Weak and Strong), and every odd index value
+ // corresponds to the same object as index-1
+ // Flipped and shifted first word is non-zero. If leading_zeros is 0 or 1, we return r_index (above).
+ // if leading zeros is 2 or 3, we return (r_index - 1) or (r_index - 2), and so forth
+ idx_t result = r_index + 1 - count_leading_zeros(cword);
+ if (aligned_left || (result >= l_index)) return result;
+ else {
+ // Sentinel value means no object found within specified range.
+ return r_index + 2;
+ }
+ } else {
+ // Flipped and shifted first word is zero. Word search through
+ // aligned up r_index for a non-zero flipped word.
+ idx_t limit = aligned_left
+ ? to_words_align_down(l_index) // Minuscule savings when aligned.
+ : to_words_align_up(l_index);
+ // Unsigned index is always >= unsigned limit if limit equals zero, so test for strictly greater than before decrement.
+ while (index-- > limit) {
+ cword = map(index) ^ flip;
+ if (cword != 0) {
+ // cword hods bits:
+ // 0x03 for the object corresponding to index (and index+1) (count_leading_zeros is 62 or 63)
+ // 0x0c for the object corresponding to index + 2 (and index+3) (count_leading_zeros is 60 or 61)
+ // and so on.
+ idx_t result = bit_index(index + 1) - (count_leading_zeros(cword) + 1);
+ if (aligned_left || (result >= l_index)) return result;
+ else {
+ // Sentinel value means no object found within specified range.
+ return r_index + 2;
+ }
+ }
+ }
+ // No bits in range; return r_index+2.
+ return r_index + 2;
+ }
+ }
+ else {
+ return r_index + 2;
+ }
+}
+
inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_one_offset(idx_t l_offset, idx_t r_offset) const {
return get_next_bit_impl(l_offset, r_offset);
}
+inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_prev_one_offset(idx_t l_offset, idx_t r_offset) const {
+ return get_prev_bit_impl(l_offset, r_offset);
+}
+
// Returns a bit mask for a range of bits [beg, end) within a single word. Each
// bit in the mask is 0 if the bit is in the range, 1 if not in the range. The
// returned mask can be used directly to clear the range, or inverted to set the
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp
index 8a52042e513..d8e0c74ea4e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp
@@ -67,8 +67,12 @@ class ShenandoahMarkingContext : public CHeapObj {
inline bool is_marked_or_old(oop obj) const;
inline bool is_marked_strong_or_old(oop obj) const;
+ // Return address of the first marked address in the range [addr,limit), or limit if no marked object found
inline HeapWord* get_next_marked_addr(const HeapWord* addr, const HeapWord* limit) const;
+ // Return address of the last marked object in range [limit, start], returning start+1 if no marked object found
+ inline HeapWord* get_prev_marked_addr(const HeapWord* limit, const HeapWord* start) const;
+
inline bool allocated_after_mark_start(const oop obj) const;
inline bool allocated_after_mark_start(const HeapWord* addr) const;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
index e3ba774283c..fe98413a8cc 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
@@ -72,6 +72,10 @@ inline HeapWord* ShenandoahMarkingContext::get_next_marked_addr(const HeapWord*
return _mark_bit_map.get_next_marked_addr(start, limit);
}
+inline HeapWord* ShenandoahMarkingContext::get_prev_marked_addr(const HeapWord* limit, const HeapWord* start) const {
+ return _mark_bit_map.get_prev_marked_addr(limit, start);
+}
+
inline bool ShenandoahMarkingContext::allocated_after_mark_start(oop obj) const {
const HeapWord* addr = cast_from_oop(obj);
return allocated_after_mark_start(addr);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
index 35d963f1801..5cccd395d38 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
@@ -196,8 +196,8 @@ class ShenandoahConcurrentCoalesceAndFillTask : public WorkerTask {
}
};
-ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity)
- : ShenandoahGeneration(OLD, max_queues, max_capacity, soft_max_capacity),
+ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues, size_t max_capacity)
+ : ShenandoahGeneration(OLD, max_queues, max_capacity),
_coalesce_and_fill_region_array(NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, ShenandoahHeap::heap()->num_regions(), mtGC)),
_old_heuristics(nullptr),
_region_balance(0),
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
index b70a8d33b95..abc865c31cd 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp
@@ -88,7 +88,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration {
bool coalesce_and_fill();
public:
- ShenandoahOldGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity);
+ ShenandoahOldGeneration(uint max_queues, size_t max_capacity);
ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
index 23c705348c4..ea94c2926e8 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
@@ -125,9 +125,8 @@ void ShenandoahDirectCardMarkRememberedSet::mark_read_table_as_clean() {
// No lock required because arguments align with card boundaries.
void ShenandoahCardCluster::reset_object_range(HeapWord* from, HeapWord* to) {
- assert(((((unsigned long long) from) & (CardTable::card_size() - 1)) == 0) &&
- ((((unsigned long long) to) & (CardTable::card_size() - 1)) == 0),
- "reset_object_range bounds must align with card boundaries");
+ assert(CardTable::is_card_aligned(from) && CardTable::is_card_aligned(to),
+ "Must align with card boundaries");
size_t card_at_start = _rs->card_index_for_addr(from);
size_t num_cards = (to - from) / CardTable::card_size_in_words();
@@ -222,31 +221,88 @@ size_t ShenandoahCardCluster::get_last_start(size_t card_index) const {
return _object_starts[card_index].offsets.last;
}
-// Given a card_index, return the starting address of the first block in the heap
-// that straddles into this card. If this card is co-initial with an object, then
-// this would return the first address of the range that this card covers, which is
-// where the card's first object also begins.
-HeapWord* ShenandoahCardCluster::block_start(const size_t card_index) const {
+HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, const ShenandoahMarkingContext* const ctx,
+ HeapWord* tams, HeapWord* end_range_of_interest) const {
HeapWord* left = _rs->addr_for_card_index(card_index);
+ assert(left < end_range_of_interest, "No meaningful work to do");
+ ShenandoahHeapRegion* region = ShenandoahHeap::heap()->heap_region_containing(left);
#ifdef ASSERT
assert(ShenandoahHeap::heap()->mode()->is_generational(), "Do not use in non-generational mode");
- ShenandoahHeapRegion* region = ShenandoahHeap::heap()->heap_region_containing(left);
assert(region->is_old(), "Do not use for young regions");
// For HumongousRegion:s it's more efficient to jump directly to the
// start region.
assert(!region->is_humongous(), "Use region->humongous_start_region() instead");
#endif
+
+ HeapWord* right = MIN2(region->top(), end_range_of_interest);
+ HeapWord* end_of_search_next = MIN2(right, tams);
+ // Since end_range_of_interest may not align on a card boundary, last_relevant_card_index is conservative. Not all of the
+ // memory within the last relevant card's span is < right.
+ size_t last_relevant_card_index;
+ if (end_range_of_interest == _end_of_heap) {
+ last_relevant_card_index = _rs->card_index_for_addr(end_range_of_interest - 1);
+ } else {
+ last_relevant_card_index = _rs->card_index_for_addr(end_range_of_interest);
+ if (_rs->addr_for_card_index(last_relevant_card_index) == end_range_of_interest) {
+ last_relevant_card_index--;
+ }
+ }
+ assert(card_index <= last_relevant_card_index, "sanity: card_index: %zu, last_relevant: %zu, left: " PTR_FORMAT
+ ", end_of_range: " PTR_FORMAT, card_index, last_relevant_card_index, p2i(left), p2i(end_range_of_interest));
+
+ // if marking context is valid and we are below tams, we use the marking bit map to find the first marked object that
+ // intersects with this card. If no such object exists, we return the first marked object that follows the start
+ // of this card's memory range if such an object is found at or before last_relevant_card_index. If there are no
+ // marked objects in this range, we return nullptr.
+ if ((ctx != nullptr) && (left < tams)) {
+ if (ctx->is_marked(left)) {
+ oop obj = cast_to_oop(left);
+ assert(oopDesc::is_oop(obj), "Should be an object");
+ return left;
+ }
+ // get the previous marked object, if any
+ if (region->bottom() < left) {
+ // In the case that this region was most recently marked as young, the fact that this region has been promoted in place
+ // denotes that final mark (Young) has completed. In the case that this region was most recently marked as old, the
+ // fact that (ctx != nullptr) denotes that old marking has completed. Otherwise, ctx would equal null.
+ HeapWord* prev = ctx->get_prev_marked_addr(region->bottom(), left - 1);
+ if (prev < left) {
+ oop obj = cast_to_oop(prev);
+ assert(oopDesc::is_oop(obj), "Should be an object");
+ HeapWord* obj_end = prev + obj->size();
+ if (obj_end > left) {
+ return prev;
+ }
+ }
+ }
+ // Either prev >= left (no previous object found), or the previous object that was found ends before my card range begins.
+ // In eiher case, find the next marked object if any on this or a following card
+ assert(!ctx->is_marked(left), "Was dealt with above");
+ assert(right > left, "We don't expect to be examining cards above the smaller of TAMS or top");
+ HeapWord* next = ctx->get_next_marked_addr(left, end_of_search_next);
+ // If end_of_search_next < right, we may return tams here, which is "marked" by default
+ if (next < right) {
+ oop obj = cast_to_oop(next);
+ assert(oopDesc::is_oop(obj), "Should be an object");
+ return next;
+ } else {
+ return nullptr;
+ }
+ }
+
+ assert((ctx == nullptr) || (left >= tams), "Should have returned above");
+
+ // The following code assumes that all data in region at or above left holds parsable objects
+ assert((left >= tams) || ShenandoahGenerationalHeap::heap()->old_generation()->is_parsable(),
+ "The code that follows expects a parsable heap");
if (starts_object(card_index) && get_first_start(card_index) == 0) {
- // This card contains a co-initial object; a fortiori, it covers
- // also the case of a card being the first in a region.
+ // This card contains a co-initial object; a fortiori, it covers also the case of a card being the first in a region.
assert(oopDesc::is_oop(cast_to_oop(left)), "Should be an object");
return left;
}
- HeapWord* p = nullptr;
- oop obj = cast_to_oop(p);
ssize_t cur_index = (ssize_t)card_index;
assert(cur_index >= 0, "Overflow");
assert(cur_index > 0, "Should have returned above");
@@ -256,37 +312,75 @@ HeapWord* ShenandoahCardCluster::block_start(const size_t card_index) const {
}
// cur_index should start an object: we should not have walked
// past the left end of the region.
- assert(cur_index >= 0 && (cur_index <= (ssize_t)card_index), "Error");
+ assert(cur_index >= 0 && (cur_index <= (ssize_t) card_index), "Error");
assert(region->bottom() <= _rs->addr_for_card_index(cur_index),
"Fell off the bottom of containing region");
assert(starts_object(cur_index), "Error");
size_t offset = get_last_start(cur_index);
// can avoid call via card size arithmetic below instead
- p = _rs->addr_for_card_index(cur_index) + offset;
+ HeapWord* p = _rs->addr_for_card_index(cur_index) + offset;
+ if ((ctx != nullptr) && (p < tams)) {
+ if (ctx->is_marked(p)) {
+ oop obj = cast_to_oop(p);
+ assert(oopDesc::is_oop(obj), "Should be an object");
+ assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr");
+ assert(p + obj->size() > left, "This object should span start of card");
+ assert(p < right, "Result must precede right");
+ return p;
+ } else {
+ // Object that spans start of card is dead, so should not be scanned
+ assert((ctx == nullptr) || (left + get_first_start(card_index) >= tams), "Should have handled this case above");
+ if (starts_object(card_index)) {
+ assert(left + get_first_start(card_index) < right, "Result must precede right");
+ return left + get_first_start(card_index);
+ } else {
+ // Spanning object is dead and this card does not start an object, so the start object is in some card that follows
+ size_t following_card_index = card_index;
+ do {
+ following_card_index++;
+ if (following_card_index > last_relevant_card_index) {
+ return nullptr;
+ }
+ } while (!starts_object(following_card_index));
+ HeapWord* result_candidate = _rs->addr_for_card_index(following_card_index) + get_first_start(following_card_index);
+ return (result_candidate >= right)? nullptr: result_candidate;
+ }
+ }
+ }
+
// Recall that we already dealt with the co-initial object case above
assert(p < left, "obj should start before left");
// While it is safe to ask an object its size in the loop that
// follows, the (ifdef'd out) loop should never be needed.
- // 1. we ask this question only for regions in the old generation
+ // 1. we ask this question only for regions in the old generation, and those
+ // that are not humongous regions
// 2. there is no direct allocation ever by mutators in old generation
- // regions. Only GC will ever allocate in old regions, and then
- // too only during promotion/evacuation phases. Thus there is no danger
+ // regions walked by this code. Only GC will ever allocate in old regions,
+ // and then too only during promotion/evacuation phases. Thus there is no danger
// of races between reading from and writing to the object start array,
// or of asking partially initialized objects their size (in the loop below).
+ // Furthermore, humongous regions (and their dirty cards) are never processed
+ // by this code.
// 3. only GC asks this question during phases when it is not concurrently
// evacuating/promoting, viz. during concurrent root scanning (before
// the evacuation phase) and during concurrent update refs (after the
// evacuation phase) of young collections. This is never called
- // during old or global collections.
+ // during global collections during marking or update refs..
// 4. Every allocation under TAMS updates the object start array.
- NOT_PRODUCT(obj = cast_to_oop(p);)
+#ifdef ASSERT
+ oop obj = cast_to_oop(p);
assert(oopDesc::is_oop(obj), "Should be an object");
-#define WALK_FORWARD_IN_BLOCK_START false
- while (WALK_FORWARD_IN_BLOCK_START && p + obj->size() < left) {
+ while (p + obj->size() < left) {
p += obj->size();
+ obj = cast_to_oop(p);
+ assert(oopDesc::is_oop(obj), "Should be an object");
+ assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr");
+ // Check assumptions in previous block comment if this assert fires
+ fatal("Should never need forward walk in block start");
}
-#undef WALK_FORWARD_IN_BLOCK_START // false
- assert(p + obj->size() > left, "obj should end after left");
+ assert(p <= left, "p should start at or before left end of card");
+ assert(p + obj->size() > left, "obj should end after left end of card");
+#endif // ASSERT
return p;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp
index 5df34159c0f..08fcd74a460 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp
@@ -351,6 +351,7 @@ class ShenandoahCardCluster: public CHeapObj {
private:
ShenandoahDirectCardMarkRememberedSet* _rs;
+ const HeapWord* _end_of_heap;
public:
static const size_t CardsPerCluster = 64;
@@ -404,6 +405,7 @@ class ShenandoahCardCluster: public CHeapObj {
ShenandoahCardCluster(ShenandoahDirectCardMarkRememberedSet* rs) {
_rs = rs;
+ _end_of_heap = ShenandoahHeap::heap()->end();
_object_starts = NEW_C_HEAP_ARRAY(crossing_info, rs->total_cards() + 1, mtGC); // the +1 is to account for card table guarding entry
for (size_t i = 0; i < rs->total_cards(); i++) {
_object_starts[i].short_word = 0;
@@ -650,12 +652,31 @@ class ShenandoahCardCluster: public CHeapObj {
size_t get_last_start(size_t card_index) const;
- // Given a card_index, return the starting address of the first block in the heap
- // that straddles into the card. If the card is co-initial with an object, then
- // this would return the starting address of the heap that this card covers.
- // Expects to be called for a card affiliated with the old generation in
- // generational mode.
- HeapWord* block_start(size_t card_index) const;
+ // Given a card_index, return the starting address of the first live object in the heap
+ // that intersects with or follows this card. This must be a valid, parsable object, and must
+ // be the first such object that intersects with this card. The object may start before,
+ // at, or after the start of the card identified by card_index, and may end in or after the card.
+ //
+ // The tams argument represents top for the enclosing region at the start of the most recently
+ // initiated concurrent old marking effort. If ctx is non-null, we use the marking context to identify
+ // marked objects below tams. Above tams, we know that every object is marked and that the memory is
+ // parsable (so we can add an object's size to its address to find the next object). If ctx is null,
+ // we use crossing maps to find where object's start, and use object sizes to walk individual objects.
+ // The region must be parsable if ctx is null.
+ //
+ // The end_range_of_interest pointer argument represents an upper bound on how far we look in the forward direction
+ // for the first object in the heap that intersects or follows this card. If there are no live objects found at
+ // an address less than end_range_of_interest returns nullptr.
+ //
+ // Expects to be called for a card in a region affiliated with the old generation of the
+ // generational heap, otherwise behavior is undefined.
+ //
+ // If not null, ctx holds the complete marking context of the old generation. If null,
+ // we expect that the marking context isn't available and the crossing maps are valid.
+ // Note that crossing maps may be invalid following class unloading and before dead
+ // or unloaded objects have been coalesced and filled. Coalesce and fill updates the crossing maps.
+ HeapWord* first_object_start(size_t card_index, const ShenandoahMarkingContext* const ctx,
+ HeapWord* tams, HeapWord* end_range_of_interest) const;
};
// ShenandoahScanRemembered is a concrete class representing the
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
index 68bec5c2071..82022420a2a 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
@@ -50,7 +50,7 @@
// degenerated execution, leading to dangling references.
template
void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t count, HeapWord* end_of_range,
- ClosureType* cl, bool use_write_table, uint worker_id) {
+ ClosureType* cl, bool use_write_table, uint worker_id) {
assert(ShenandoahHeap::heap()->old_generation()->is_parsable(), "Old generation regions must be parsable for remembered set scan");
// If old-gen evacuation is active, then MarkingContext for old-gen heap regions is valid. We use the MarkingContext
@@ -102,7 +102,7 @@ void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t cou
// tams and ctx below are for old generation marking. As such, young gen roots must
// consider everything above tams, since it doesn't represent a TAMS for young gen's
// SATB marking.
- const HeapWord* tams = (ctx == nullptr ? region->bottom() : ctx->top_at_mark_start(region));
+ HeapWord* const tams = (ctx == nullptr ? region->bottom() : ctx->top_at_mark_start(region));
NOT_PRODUCT(ShenandoahCardStats stats(whole_cards, card_stats(worker_id));)
@@ -162,19 +162,37 @@ void ShenandoahScanRemembered::process_clusters(size_t first_cluster, size_t cou
// [left, right) is a maximal right-open interval of dirty cards
HeapWord* left = _rs->addr_for_card_index(dirty_l); // inclusive
HeapWord* right = _rs->addr_for_card_index(dirty_r + 1); // exclusive
+ if (end_addr <= left) {
+ // The range of addresses to be scanned is empty
+ continue;
+ }
// Clip right to end_addr established above (still exclusive)
right = MIN2(right, end_addr);
assert(right <= region->top() && end_addr <= region->top(), "Busted bounds");
const MemRegion mr(left, right);
- // NOTE: We'll not call block_start() repeatedly
- // on a very large object if its head card is dirty. If not,
- // (i.e. the head card is clean) we'll call it each time we
- // process a new dirty range on the object. This is always
- // the case for large object arrays, which are typically more
+ // NOTE: We'll not call first_object_start() repeatedly
+ // on a very large object, i.e. one spanning multiple cards,
+ // if its head card is dirty. If not, (i.e. its head card is clean)
+ // we'll call it each time we process a new dirty range on the object.
+ // This is always the case for large object arrays, which are typically more
// common.
- HeapWord* p = _scc->block_start(dirty_l);
+ assert(ctx != nullptr || heap->old_generation()->is_parsable(), "Error");
+ HeapWord* p = _scc->first_object_start(dirty_l, ctx, tams, right);
+ assert((p == nullptr) || (p < right), "No first object found is denoted by nullptr, p: "
+ PTR_FORMAT ", right: " PTR_FORMAT ", end_addr: " PTR_FORMAT ", next card addr: " PTR_FORMAT,
+ p2i(p), p2i(right), p2i(end_addr), p2i(_rs->addr_for_card_index(dirty_r + 1)));
+ if (p == nullptr) {
+ // There are no live objects to be scanned in this dirty range. cur_index identifies first card in this
+ // uninteresting dirty range. At top of next loop iteration, we will either end the looop
+ // (because cur_index < start_card_index) or we will begin the search for a range of clean cards.
+ continue;
+ }
+
oop obj = cast_to_oop(p);
+ assert(oopDesc::is_oop(obj), "Not an object at " PTR_FORMAT ", left: " PTR_FORMAT ", right: " PTR_FORMAT,
+ p2i(p), p2i(left), p2i(right));
+ assert(ctx==nullptr || ctx->is_marked(obj), "Error");
// PREFIX: The object that straddles into this range of dirty cards
// from the left may be subject to special treatment unless
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp
index daf5d456af5..849ab691dcf 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp
@@ -30,8 +30,8 @@
#include "gc/shenandoah/shenandoahUtils.hpp"
#include "gc/shenandoah/shenandoahYoungGeneration.hpp"
-ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) :
- ShenandoahGeneration(YOUNG, max_queues, max_capacity, soft_max_capacity),
+ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity) :
+ ShenandoahGeneration(YOUNG, max_queues, max_capacity),
_old_gen_task_queues(nullptr) {
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp
index a8ebab507b6..14f9a9b3004 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp
@@ -34,7 +34,7 @@ class ShenandoahYoungGeneration : public ShenandoahGeneration {
ShenandoahYoungHeuristics* _young_heuristics;
public:
- ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t max_soft_capacity);
+ ShenandoahYoungGeneration(uint max_queues, size_t max_capacity);
ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode) override;
diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp
index a273df61922..bd5797be0a0 100644
--- a/src/hotspot/share/jfr/jfr.cpp
+++ b/src/hotspot/share/jfr/jfr.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
+#include "jfr/recorder/service/jfrRecorderService.hpp"
#include "jfr/recorder/repository/jfrRepository.hpp"
#include "jfr/support/jfrKlassExtension.hpp"
#include "jfr/support/jfrResolution.hpp"
@@ -43,6 +44,7 @@
#include "runtime/java.hpp"
#include "runtime/javaThread.hpp"
+
bool Jfr::is_enabled() {
return JfrRecorder::is_enabled();
}
@@ -151,9 +153,9 @@ void Jfr::on_resolution(const Method* caller, const Method* target, TRAPS) {
}
#endif
-void Jfr::on_vm_shutdown(bool emit_old_object_samples, bool emit_event_shutdown, bool halt) {
+void Jfr::on_vm_shutdown(bool exception_handler /* false */, bool halt /* false */, bool oom /* false */) {
if (!halt && JfrRecorder::is_recording()) {
- JfrEmergencyDump::on_vm_shutdown(emit_old_object_samples, emit_event_shutdown);
+ JfrEmergencyDump::on_vm_shutdown(exception_handler, oom);
}
}
@@ -170,3 +172,9 @@ bool Jfr::on_flight_recorder_option(const JavaVMOption** option, char* delimiter
bool Jfr::on_start_flight_recording_option(const JavaVMOption** option, char* delimiter) {
return JfrOptionSet::parse_start_flight_recording_option(option, delimiter);
}
+
+void Jfr::on_report_java_out_of_memory() {
+ if (CrashOnOutOfMemoryError && JfrRecorder::is_recording()) {
+ JfrRecorderService::emit_leakprofiler_events_on_oom();
+ }
+}
diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp
index 2e1fc738a61..a7565620bbd 100644
--- a/src/hotspot/share/jfr/jfr.hpp
+++ b/src/hotspot/share/jfr/jfr.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, 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
@@ -70,7 +70,7 @@ class Jfr : AllStatic {
static void on_resolution(const Method* caller, const Method* target, TRAPS);
static void on_java_thread_start(JavaThread* starter, JavaThread* startee);
static void on_set_current_thread(JavaThread* jt, oop thread);
- static void on_vm_shutdown(bool emit_old_object_samples, bool emit_event_shutdown, bool halt = false);
+ static void on_vm_shutdown(bool exception_handler = false, bool halt = false, bool oom = false);
static void on_vm_error_report(outputStream* st);
static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter);
static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter);
@@ -78,6 +78,7 @@ class Jfr : AllStatic {
static void initialize_main_thread(JavaThread* jt);
static bool has_sample_request(JavaThread* jt);
static void check_and_process_sample_request(JavaThread* jt);
+ static void on_report_java_out_of_memory();
};
#endif // SHARE_JFR_JFR_HPP
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
index a09da529b1b..0b4ab532064 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2026, 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
@@ -364,8 +364,7 @@ JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jclass jvm, jb
JVM_END
NO_TRANSITION(void, jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean emit_all, jboolean skip_bfs))
- JfrRecorderService service;
- service.emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
+ JfrRecorderService::emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
NO_TRANSITION_END
JVM_ENTRY_NO_ENV(void, jfr_exclude_thread(JNIEnv* env, jclass jvm, jobject t))
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp
index fd7226eab2d..a59503f50d8 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp
@@ -25,7 +25,6 @@
#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "logging/log.hpp"
-
#if defined(LINUX)
#include "jfr/periodic/sampling/jfrThreadSampling.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
@@ -68,7 +67,7 @@ static JavaThread* get_java_thread_if_valid() {
}
JfrCPUTimeTraceQueue::JfrCPUTimeTraceQueue(u4 capacity) :
- _data(nullptr), _capacity(capacity), _head(0), _lost_samples(0) {
+ _data(nullptr), _capacity(capacity), _head(0), _lost_samples(0), _lost_samples_due_to_queue_full(0) {
if (capacity != 0) {
_data = JfrCHeapObj::new_array(capacity);
}
@@ -111,10 +110,13 @@ void JfrCPUTimeTraceQueue::set_size(u4 size) {
}
u4 JfrCPUTimeTraceQueue::capacity() const {
- return _capacity;
+ return Atomic::load_acquire(&_capacity);
}
void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) {
+ if (capacity == Atomic::load(&_capacity)) {
+ return;
+ }
_head = 0;
if (_data != nullptr) {
assert(_capacity != 0, "invariant");
@@ -125,7 +127,7 @@ void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) {
} else {
_data = nullptr;
}
- _capacity = capacity;
+ Atomic::release_store(&_capacity, capacity);
}
bool JfrCPUTimeTraceQueue::is_empty() const {
@@ -141,28 +143,51 @@ void JfrCPUTimeTraceQueue::increment_lost_samples() {
Atomic::inc(&_lost_samples);
}
+void JfrCPUTimeTraceQueue::increment_lost_samples_due_to_queue_full() {
+ Atomic::inc(&_lost_samples_due_to_queue_full);
+}
+
u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() {
return Atomic::xchg(&_lost_samples, (u4)0);
}
-void JfrCPUTimeTraceQueue::resize(u4 capacity) {
- if (capacity != _capacity) {
- set_capacity(capacity);
- }
+u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples_due_to_queue_full() {
+ return Atomic::xchg(&_lost_samples_due_to_queue_full, (u4)0);
}
-void JfrCPUTimeTraceQueue::resize_for_period(u4 period_millis) {
- u4 capacity = CPU_TIME_QUEUE_CAPACITY;
- if (period_millis > 0 && period_millis < 10) {
- capacity = (u4) ((double) capacity * 10 / period_millis);
- }
- resize(capacity);
+void JfrCPUTimeTraceQueue::init() {
+ set_capacity(JfrCPUTimeTraceQueue::CPU_TIME_QUEUE_INITIAL_CAPACITY);
}
void JfrCPUTimeTraceQueue::clear() {
Atomic::release_store(&_head, (u4)0);
}
+void JfrCPUTimeTraceQueue::resize_if_needed() {
+ u4 lost_samples_due_to_queue_full = get_and_reset_lost_samples_due_to_queue_full();
+ if (lost_samples_due_to_queue_full == 0) {
+ return;
+ }
+ u4 capacity = Atomic::load(&_capacity);
+ if (capacity < CPU_TIME_QUEUE_MAX_CAPACITY) {
+ float ratio = (float)lost_samples_due_to_queue_full / (float)capacity;
+ int factor = 1;
+ if (ratio > 8) { // idea is to quickly scale the queue in the worst case
+ factor = ratio;
+ } else if (ratio > 2) {
+ factor = 8;
+ } else if (ratio > 0.5) {
+ factor = 4;
+ } else if (ratio > 0.01) {
+ factor = 2;
+ }
+ if (factor > 1) {
+ u4 new_capacity = MIN2(CPU_TIME_QUEUE_MAX_CAPACITY, capacity * factor);
+ set_capacity(new_capacity);
+ }
+ }
+}
+
// A throttle is either a rate or a fixed period
class JfrCPUSamplerThrottle {
@@ -206,6 +231,8 @@ class JfrCPUSamplerThread : public NonJavaThread {
volatile bool _is_async_processing_of_cpu_time_jfr_requests_triggered;
volatile bool _warned_about_timer_creation_failure;
volatile bool _signal_handler_installed;
+ DEBUG_ONLY(volatile bool _out_of_stack_walking_enabled;)
+ DEBUG_ONLY(volatile u8 _out_of_stack_walking_iterations;)
static const u4 STOP_SIGNAL_BIT = 0x80000000;
@@ -252,6 +279,16 @@ class JfrCPUSamplerThread : public NonJavaThread {
virtual void print_on(outputStream* st) const;
void trigger_async_processing_of_cpu_time_jfr_requests();
+
+ #ifdef ASSERT
+ void set_out_of_stack_walking_enabled(bool runnable) {
+ Atomic::release_store(&_out_of_stack_walking_enabled, runnable);
+ }
+
+ u8 out_of_stack_walking_iterations() const {
+ return Atomic::load(&_out_of_stack_walking_iterations);
+ }
+ #endif
};
JfrCPUSamplerThread::JfrCPUSamplerThread(JfrCPUSamplerThrottle& throttle) :
@@ -277,7 +314,7 @@ void JfrCPUSamplerThread::on_javathread_create(JavaThread* thread) {
}
JfrThreadLocal* tl = thread->jfr_thread_local();
assert(tl != nullptr, "invariant");
- tl->cpu_time_jfr_queue().resize_for_period(_current_sampling_period_ns / 1000000);
+ tl->cpu_time_jfr_queue().init();
timer_t timerid;
if (create_timer_for_thread(thread, timerid)) {
tl->set_cpu_timer(&timerid);
@@ -296,12 +333,14 @@ void JfrCPUSamplerThread::on_javathread_terminate(JavaThread* thread) {
if (timer == nullptr) {
return; // no timer was created for this thread
}
+ tl->acquire_cpu_time_jfr_dequeue_lock();
tl->unset_cpu_timer();
tl->deallocate_cpu_time_jfr_queue();
s4 lost_samples = tl->cpu_time_jfr_queue().lost_samples();
if (lost_samples > 0) {
JfrCPUTimeThreadSampling::send_lost_event(JfrTicks::now(), JfrThreadLocal::thread_id(thread), lost_samples);
}
+ tl->release_cpu_time_jfr_queue_lock();
}
void JfrCPUSamplerThread::start_thread() {
@@ -354,10 +393,12 @@ void JfrCPUSamplerThread::run() {
recompute_period_if_needed();
last_recompute_check = os::javaTimeNanos();
}
-
- if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) {
- stackwalk_threads_in_native();
- }
+ DEBUG_ONLY(if (Atomic::load_acquire(&_out_of_stack_walking_enabled)) {)
+ if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) {
+ DEBUG_ONLY(Atomic::inc(&_out_of_stack_walking_iterations);)
+ stackwalk_threads_in_native();
+ }
+ DEBUG_ONLY(})
os::naked_sleep(100);
}
}
@@ -547,6 +588,21 @@ void JfrCPUTimeThreadSampling::handle_timer_signal(siginfo_t* info, void* contex
_sampler->decrement_signal_handler_count();
}
+#ifdef ASSERT
+void JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) {
+ if (_instance != nullptr && _instance->_sampler != nullptr) {
+ _instance->_sampler->set_out_of_stack_walking_enabled(runnable);
+ }
+}
+
+u8 JfrCPUTimeThreadSampling::out_of_stack_walking_iterations() {
+ if (_instance != nullptr && _instance->_sampler != nullptr) {
+ return _instance->_sampler->out_of_stack_walking_iterations();
+ }
+ return 0;
+}
+#endif
+
void JfrCPUSamplerThread::sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now) {
JfrSampleRequestBuilder::build_cpu_time_sample_request(request, ucontext, jt, jt->jfr_thread_local(), now);
}
@@ -592,6 +648,7 @@ void JfrCPUSamplerThread::handle_timer_signal(siginfo_t* info, void* context) {
}
} else {
queue.increment_lost_samples();
+ queue.increment_lost_samples_due_to_queue_full();
}
if (jt->thread_state() == _thread_in_native) {
@@ -815,4 +872,10 @@ void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread* thread) {
void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread* thread) {
}
+#ifdef ASSERT
+static void set_out_of_stack_walking_enabled(bool runnable) {
+ warn();
+}
+#endif
+
#endif // defined(LINUX) && defined(INCLUDE_JFR)
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp
index dae0be5c3a7..e17e63fc3ed 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp
@@ -50,12 +50,15 @@ class JfrCPUTimeTraceQueue {
static const u4 CPU_TIME_QUEUE_CAPACITY = 500;
JfrCPUTimeSampleRequest* _data;
- u4 _capacity;
+ volatile u4 _capacity;
// next unfilled index
volatile u4 _head;
volatile u4 _lost_samples;
+ volatile u4 _lost_samples_due_to_queue_full;
+ static const u4 CPU_TIME_QUEUE_INITIAL_CAPACITY = 20;
+ static const u4 CPU_TIME_QUEUE_MAX_CAPACITY = 2000;
public:
JfrCPUTimeTraceQueue(u4 capacity);
@@ -81,12 +84,17 @@ class JfrCPUTimeTraceQueue {
void increment_lost_samples();
+ void increment_lost_samples_due_to_queue_full();
+
// returns the previous lost samples count
u4 get_and_reset_lost_samples();
- void resize(u4 capacity);
+ u4 get_and_reset_lost_samples_due_to_queue_full();
+
+ void resize_if_needed();
- void resize_for_period(u4 period_millis);
+ // init the queue capacity
+ void init();
void clear();
@@ -130,6 +138,10 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj {
static void send_lost_event(const JfrTicks& time, traceid tid, s4 lost_samples);
static void trigger_async_processing_of_cpu_time_jfr_requests();
+
+ DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable);)
+
+ DEBUG_ONLY(static u8 out_of_stack_walking_iterations();)
};
#else
@@ -150,6 +162,8 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj {
static void on_javathread_create(JavaThread* thread);
static void on_javathread_terminate(JavaThread* thread);
+ DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable));
+ DEBUG_ONLY(static u8 out_of_stack_walking_iterations();)
};
#endif // defined(LINUX)
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
index cc20323eef2..596702a53dd 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026, 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
@@ -232,41 +232,50 @@ void JfrSamplerThread::task_stacktrace(JfrSampleRequestType type, JavaThread** l
JavaThread* start = nullptr;
elapsedTimer sample_time;
sample_time.start();
- ThreadsListHandle tlh;
- // Resolve a sample session relative start position index into the thread list array.
- // In cases where the last sampled thread is null or not-null but stale, find_index() returns -1.
- _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
- JavaThread* current = _cur_index != -1 ? *last_thread : nullptr;
-
- while (num_samples < sample_limit) {
- current = next_thread(tlh.list(), start, current);
- if (current == nullptr) {
- break;
- }
- if (is_excluded(current)) {
- continue;
- }
- if (start == nullptr) {
- start = current; // remember the thread where we started to attempt sampling
- }
- bool success;
- if (JAVA_SAMPLE == type) {
- success = sample_java_thread(current);
- } else {
- assert(type == NATIVE_SAMPLE, "invariant");
- success = sample_native_thread(current);
- }
- if (success) {
- num_samples++;
- }
- if (SafepointSynchronize::is_at_safepoint()) {
- // For _thread_in_native, we cannot get the Threads_lock.
- // For _thread_in_Java, well, there are none.
- break;
+ {
+ /*
+ * Take the Threads_lock for three purposes:
+ *
+ * 1) Avoid sampling right through a safepoint,
+ * which could result in touching oops in case of virtual threads.
+ * 2) Prevent JFR from issuing an epoch rotation while the sampler thread
+ * is actively processing a thread in state native, as both threads are outside the safepoint protocol.
+ * 3) Some operating systems (BSD / Mac) require a process lock when sending a signal with pthread_kill.
+ * Holding the Threads_lock prevents a JavaThread from calling os::create_thread(), which also takes the process lock.
+ * In a sense, we provide a coarse signal mask, so we can always send the resume signal.
+ */
+ MutexLocker tlock(Threads_lock);
+ ThreadsListHandle tlh;
+ // Resolve a sample session relative start position index into the thread list array.
+ // In cases where the last sampled thread is null or not-null but stale, find_index() returns -1.
+ _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
+ JavaThread* current = _cur_index != -1 ? *last_thread : nullptr;
+
+ while (num_samples < sample_limit) {
+ current = next_thread(tlh.list(), start, current);
+ if (current == nullptr) {
+ break;
+ }
+ if (is_excluded(current)) {
+ continue;
+ }
+ if (start == nullptr) {
+ start = current; // remember the thread where we started to attempt sampling
+ }
+ bool success;
+ if (JAVA_SAMPLE == type) {
+ success = sample_java_thread(current);
+ } else {
+ assert(type == NATIVE_SAMPLE, "invariant");
+ success = sample_native_thread(current);
+ }
+ if (success) {
+ num_samples++;
+ }
}
- }
- *last_thread = current; // remember the thread we last attempted to sample
+ *last_thread = current; // remember the thread we last attempted to sample
+ }
sample_time.stop();
log_trace(jfr)("JFR thread sampling done in %3.7f secs with %d java %d native samples",
sample_time.seconds(), type == JAVA_SAMPLE ? num_samples : 0, type == NATIVE_SAMPLE ? num_samples : 0);
@@ -297,6 +306,7 @@ class OSThreadSampler : public SuspendedThreadTask {
// Sampling a thread in state _thread_in_Java
// involves a platform-specific thread suspend and CPU context retrieval.
bool JfrSamplerThread::sample_java_thread(JavaThread* jt) {
+ assert_lock_strong(Threads_lock);
if (jt->thread_state() != _thread_in_Java) {
return false;
}
@@ -328,6 +338,7 @@ static JfrSamplerThread* _sampler_thread = nullptr;
// without thread suspension and CPU context retrieval,
// if we carefully order the loads of the thread state.
bool JfrSamplerThread::sample_native_thread(JavaThread* jt) {
+ assert_lock_strong(Threads_lock);
if (jt->thread_state() != _thread_in_native) {
return false;
}
@@ -343,24 +354,14 @@ bool JfrSamplerThread::sample_native_thread(JavaThread* jt) {
SafepointMechanism::arm_local_poll_release(jt);
- // Take the Threads_lock for two purposes:
- // 1) Avoid sampling through a safepoint which could result
- // in touching oops in case of virtual threads.
- // 2) Prevent JFR from issuing an epoch rotation while the sampler thread
- // is actively processing a thread in native, as both threads are now
- // outside the safepoint protocol.
-
- // OrderAccess::fence() as part of acquiring the lock prevents loads from floating up.
- JfrMutexTryLock threads_lock(Threads_lock);
-
- if (!threads_lock.acquired() || !jt->has_last_Java_frame()) {
- // Remove the native sample request and release the potentially waiting thread.
- JfrSampleMonitor jsm(tl);
- return false;
+ // Separate the arming of the poll (above) from the reading of JavaThread state (below).
+ if (UseSystemMemoryBarrier) {
+ SystemMemoryBarrier::emit();
+ } else {
+ OrderAccess::fence();
}
- if (jt->thread_state() != _thread_in_native) {
- assert_lock_strong(Threads_lock);
+ if (jt->thread_state() != _thread_in_native || !jt->has_last_Java_frame()) {
JfrSampleMonitor jsm(tl);
if (jsm.is_waiting()) {
// The thread has already returned from native,
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
index ddc9d59b295..534c9996cfe 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
@@ -217,7 +217,8 @@ static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame,
const PcDesc* const pc_desc = get_pc_desc(sampled_nm, sampled_pc);
if (is_valid(pc_desc)) {
intptr_t* const synthetic_sp = sender_sp - sampled_nm->frame_size();
- top_frame = frame(synthetic_sp, synthetic_sp, sender_sp, pc_desc->real_pc(sampled_nm), sampled_nm);
+ intptr_t* const synthetic_fp = sender_sp AARCH64_ONLY( - frame::sender_sp_offset);
+ top_frame = frame(synthetic_sp, synthetic_sp, synthetic_fp, pc_desc->real_pc(sampled_nm), sampled_nm);
in_continuation = is_in_continuation(top_frame, jt);
return true;
}
@@ -368,6 +369,7 @@ static void drain_enqueued_cpu_time_requests(const JfrTicks& now, JfrThreadLocal
tl->set_has_cpu_time_jfr_requests(false);
if (queue.lost_samples() > 0) {
JfrCPUTimeThreadSampling::send_lost_event( now, JfrThreadLocal::thread_id(jt), queue.get_and_reset_lost_samples());
+ queue.resize_if_needed();
}
if (lock) {
tl->release_cpu_time_jfr_queue_lock();
diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
index da619425393..e0c5d36a3c7 100644
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,9 @@
#include "runtime/javaThread.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/vmOperations.hpp"
+#include "runtime/vmThread.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/ostream.hpp"
@@ -450,25 +453,14 @@ const char* JfrEmergencyDump::chunk_path(const char* repository_path) {
*
* If we end up deadlocking in the attempt of dumping out jfr data,
* we rely on the WatcherThread task "is_error_reported()",
-* to exit the VM after a hard-coded timeout (disallow WatcherThread to emergency dump).
+* to exit the VM after a hard-coded timeout (the reason
+* for disallowing the WatcherThread to issue an emergency dump).
* This "safety net" somewhat explains the aggressiveness in this attempt.
*
*/
-static bool prepare_for_emergency_dump(Thread* thread) {
+static void release_locks(Thread* thread) {
assert(thread != nullptr, "invariant");
- if (thread->is_Watcher_thread()) {
- // need WatcherThread as a safeguard against potential deadlocks
- return false;
- }
-
-#ifdef ASSERT
- Mutex* owned_lock = thread->owned_locks();
- while (owned_lock != nullptr) {
- Mutex* next = owned_lock->next();
- owned_lock->unlock();
- owned_lock = next;
- }
-#endif // ASSERT
+ assert(!thread->is_Java_thread() || JavaThread::cast(thread)->thread_state() == _thread_in_vm, "invariant");
if (Threads_lock->owned_by_self()) {
Threads_lock->unlock();
@@ -517,24 +509,18 @@ static bool prepare_for_emergency_dump(Thread* thread) {
if (JfrStacktrace_lock->owned_by_self()) {
JfrStacktrace_lock->unlock();
}
- return true;
-}
-
-static volatile int jfr_shutdown_lock = 0;
-
-static bool guard_reentrancy() {
- return Atomic::cmpxchg(&jfr_shutdown_lock, 0, 1) == 0;
}
class JavaThreadInVMAndNative : public StackObj {
private:
- JavaThread* const _jt;
+ JavaThread* _jt;
JavaThreadState _original_state;
public:
- JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? JavaThread::cast(t) : nullptr),
+ JavaThreadInVMAndNative(Thread* t) : _jt(nullptr),
_original_state(_thread_max_state) {
- if (_jt != nullptr) {
+ if (t != nullptr && t->is_Java_thread()) {
+ _jt = JavaThread::cast(t);
_original_state = _jt->thread_state();
if (_original_state != _thread_in_vm) {
_jt->set_thread_state(_thread_in_vm);
@@ -544,6 +530,7 @@ class JavaThreadInVMAndNative : public StackObj {
~JavaThreadInVMAndNative() {
if (_original_state != _thread_max_state) {
+ assert(_jt != nullptr, "invariant");
_jt->set_thread_state(_original_state);
}
}
@@ -556,35 +543,82 @@ class JavaThreadInVMAndNative : public StackObj {
}
};
-static void post_events(bool emit_old_object_samples, bool emit_event_shutdown, Thread* thread) {
- if (emit_old_object_samples) {
- LeakProfiler::emit_events(max_jlong, false, false);
- }
- if (emit_event_shutdown) {
+static void post_events(bool exception_handler, bool oom, Thread * thread) {
+ if (exception_handler) {
EventShutdown e;
- e.set_reason("VM Error");
+ e.set_reason(oom ? "CrashOnOutOfMemoryError" : "VM Error");
e.commit();
}
EventDumpReason event;
- event.set_reason(emit_old_object_samples ? "Out of Memory" : "Crash");
+ event.set_reason(exception_handler && oom ? "CrashOnOutOfMemoryError" : exception_handler ? "Crash" : "Out of Memory");
event.set_recordingId(-1);
event.commit();
}
-void JfrEmergencyDump::on_vm_shutdown(bool emit_old_object_samples, bool emit_event_shutdown) {
- if (!guard_reentrancy()) {
- return;
+static volatile traceid _jfr_shutdown_tid = 0;
+
+static bool guard_reentrancy() {
+ const traceid shutdown_tid = Atomic::load(&_jfr_shutdown_tid);
+ if (shutdown_tid == max_julong) {
+ // Someone tried but did not have a proper thread for the purpose.
+ return false;
}
- Thread* thread = Thread::current_or_null_safe();
- if (thread == nullptr) {
+ if (shutdown_tid == 0) {
+ Thread* const thread = Thread::current_or_null_safe();
+ const traceid tid = thread != nullptr ? JFR_JVM_THREAD_ID(thread) : max_julong;
+ if (Atomic::cmpxchg(&_jfr_shutdown_tid, shutdown_tid, tid) != shutdown_tid) {
+ JavaThreadInVMAndNative jtivm(thread);
+ if (thread != nullptr) {
+ release_locks(thread);
+ }
+ log_info(jfr, system)("A jfr emergency dump is already in progress, waiting for thread id " UINT64_FORMAT_X, Atomic::load(&_jfr_shutdown_tid));
+ // Transition to a safe safepoint state for the infinite sleep. A nop for non-java threads.
+ jtivm.transition_to_native();
+ os::infinite_sleep(); // stay here until we exit normally or crash.
+ ShouldNotReachHere();
+ }
+ return tid != max_julong;
+ }
+ // Recursive case
+ assert(JFR_JVM_THREAD_ID(Thread::current_or_null_safe()) == shutdown_tid, "invariant");
+ return false;
+}
+
+void JfrEmergencyDump::on_vm_shutdown(bool exception_handler, bool oom) {
+ if (!guard_reentrancy()) {
return;
}
+
+ Thread* const thread = Thread::current_or_null_safe();
+ assert(thread != nullptr, "invariant");
+
// Ensure a JavaThread is _thread_in_vm when we make this call
JavaThreadInVMAndNative jtivm(thread);
- if (!prepare_for_emergency_dump(thread)) {
+ post_events(exception_handler, oom, thread);
+
+ if (thread->is_Watcher_thread()) {
+ // We cannot attempt an emergency dump using the Watcher thread
+ // because we rely on the WatcherThread task "is_error_reported()",
+ // to exit the VM after a hardcoded timeout, should the relatively
+ // risky operation of an emergency dump fail (deadlock, livelock).
+ log_warning(jfr, system)
+ ("The Watcher thread crashed so no jfr emergency dump will be generated.");
return;
}
- post_events(emit_old_object_samples, emit_event_shutdown, thread);
+
+ if (thread->is_VM_thread()) {
+ const VM_Operation* const operation = VMThread::vm_operation();
+ if (operation != nullptr && operation->type() == VM_Operation::VMOp_JFROldObject) {
+ // We will not be able to issue a rotation because the rotation lock
+ // is held by the JFR Recorder Thread that issued the VM_Operation.
+ log_warning(jfr, system)
+ ("The VM Thread crashed as part of emitting leak profiler events so no jfr emergency dump will be generated.");
+ return;
+ }
+ }
+
+ release_locks(thread);
+
// if JavaThread, transition to _thread_in_native to issue a final flushpoint
NoHandleMark nhm;
jtivm.transition_to_native();
diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp
index 04c2851a516..b337d73364a 100644
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, 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
@@ -39,7 +39,7 @@ class JfrEmergencyDump : AllStatic {
static const char* chunk_path(const char* repository_path);
static void on_vm_error(const char* repository_path);
static void on_vm_error_report(outputStream* st, const char* repository_path);
- static void on_vm_shutdown(bool emit_old_object_samples, bool emit_event_shutdown);
+ static void on_vm_shutdown(bool exception_handler, bool oom);
};
#endif // SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP
diff --git a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp
index b1bddfff466..0c4874e5c04 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2026, 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
@@ -34,7 +34,8 @@
(MSGBIT(MSG_START)) | \
(MSGBIT(MSG_CLONE_IN_MEMORY)) | \
(MSGBIT(MSG_VM_ERROR)) | \
- (MSGBIT(MSG_FLUSHPOINT)) \
+ (MSGBIT(MSG_FLUSHPOINT)) | \
+ (MSGBIT(MSG_EMIT_LEAKP_REFCHAINS)) \
)
static JfrPostBox* _instance = nullptr;
@@ -165,7 +166,7 @@ void JfrPostBox::notify_waiters() {
assert(JfrMsg_lock->owned_by_self(), "incrementing _msg_handled_serial is protected by JfrMsg_lock.");
// Update made visible on release of JfrMsg_lock via fence instruction in Monitor::IUnlock.
++_msg_handled_serial;
- JfrMsg_lock->notify();
+ JfrMsg_lock->notify_all();
}
// safeguard to ensure no threads are left waiting
diff --git a/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp b/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp
index 10457261643..92f70b1dc9b 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2026, 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
@@ -43,6 +43,7 @@ enum JFR_Msg {
MSG_SHUTDOWN,
MSG_VM_ERROR,
MSG_FLUSHPOINT,
+ MSG_EMIT_LEAKP_REFCHAINS,
MSG_NO_OF_MSGS
};
@@ -51,23 +52,25 @@ enum JFR_Msg {
*
* Synchronous messages (posting thread waits for message completion):
*
- * MSG_CLONE_IN_MEMORY (0) ; MSGBIT(MSG_CLONE_IN_MEMORY) == (1 << 0) == 0x1
- * MSG_START(1) ; MSGBIT(MSG_START) == (1 << 0x1) == 0x2
- * MSG_STOP (2) ; MSGBIT(MSG_STOP) == (1 << 0x2) == 0x4
- * MSG_ROTATE (3) ; MSGBIT(MSG_ROTATE) == (1 << 0x3) == 0x8
- * MSG_VM_ERROR (8) ; MSGBIT(MSG_VM_ERROR) == (1 << 0x8) == 0x100
- * MSG_FLUSHPOINT (9) ; MSGBIT(MSG_FLUSHPOINT) == (1 << 0x9) == 0x200
+ * MSG_CLONE_IN_MEMORY (0) ; MSGBIT(MSG_CLONE_IN_MEMORY) == (1 << 0) == 0x1
+ * MSG_START(1) ; MSGBIT(MSG_START) == (1 << 0x1) == 0x2
+ * MSG_STOP (2) ; MSGBIT(MSG_STOP) == (1 << 0x2) == 0x4
+ * MSG_ROTATE (3) ; MSGBIT(MSG_ROTATE) == (1 << 0x3) == 0x8
+ * MSG_VM_ERROR (8) ; MSGBIT(MSG_VM_ERROR) == (1 << 0x8) == 0x100
+ * MSG_FLUSHPOINT (9) ; MSGBIT(MSG_FLUSHPOINT) == (1 << 0x9) == 0x200
+ * MSG_EMIT_LEAKP_REFCHAINS (10); MSGBIT(MSG_EMIT_LEAKP_REFCHAINS) == (1 << 0xa) == 0x400
*
* Asynchronous messages (posting thread returns immediately upon deposit):
*
- * MSG_FULLBUFFER (4) ; MSGBIT(MSG_FULLBUFFER) == (1 << 0x4) == 0x10
- * MSG_CHECKPOINT (5) ; MSGBIT(CHECKPOINT) == (1 << 0x5) == 0x20
- * MSG_WAKEUP (6) ; MSGBIT(WAKEUP) == (1 << 0x6) == 0x40
- * MSG_SHUTDOWN (7) ; MSGBIT(MSG_SHUTDOWN) == (1 << 0x7) == 0x80
+ * MSG_FULLBUFFER (4) ; MSGBIT(MSG_FULLBUFFER) == (1 << 0x4) == 0x10
+ * MSG_CHECKPOINT (5) ; MSGBIT(CHECKPOINT) == (1 << 0x5) == 0x20
+ * MSG_WAKEUP (6) ; MSGBIT(WAKEUP) == (1 << 0x6) == 0x40
+ * MSG_SHUTDOWN (7) ; MSGBIT(MSG_SHUTDOWN) == (1 << 0x7) == 0x80
*/
class JfrPostBox : public JfrCHeapObj {
friend class JfrRecorder;
+ friend class JfrRecorderService;
public:
void post(JFR_Msg msg);
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
index f0170bac460..a136f8f1476 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2026, 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
@@ -54,6 +54,7 @@
#include "runtime/safepoint.hpp"
#include "runtime/vmOperations.hpp"
#include "runtime/vmThread.hpp"
+#include "utilities/growableArray.hpp"
// incremented on each flushpoint
static u8 flushpoint_id = 0;
@@ -413,6 +414,7 @@ class JfrSafepointWriteVMOperation : public VM_Operation {
JfrRecorderService::JfrRecorderService() :
_checkpoint_manager(JfrCheckpointManager::instance()),
_chunkwriter(JfrRepository::chunkwriter()),
+ _post_box(JfrPostBox::instance()),
_repository(JfrRepository::instance()),
_stack_trace_repository(JfrStackTraceRepository::instance()),
_storage(JfrStorage::instance()),
@@ -531,6 +533,7 @@ void JfrRecorderService::rotate(int msgs) {
return;
}
if (msgs & MSGBIT(MSG_VM_ERROR)) {
+ stop();
vm_error_rotation();
return;
}
@@ -690,17 +693,173 @@ void JfrRecorderService::evaluate_chunk_size_for_rotation() {
JfrChunkRotation::evaluate(_chunkwriter);
}
-void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs) {
- DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
- // Take the rotation lock to exclude flush() during event emits. This is because event emit
- // also creates a number checkpoint events. Those checkpoint events require a future typeset checkpoint
- // event for completeness, i.e. to be generated before being flushed to a segment.
+// LeakProfiler event serialization support.
+
+struct JfrLeakProfilerEmitRequest {
+ int64_t cutoff_ticks;
+ bool emit_all;
+ bool skip_bfs;
+ bool oom;
+};
+
+typedef GrowableArrayCHeap JfrLeakProfilerEmitRequestQueue;
+static JfrLeakProfilerEmitRequestQueue* _queue = nullptr;
+constexpr const static int64_t _no_path_to_gc_roots = 0;
+static bool _oom_emit_request_posted = false;
+static bool _oom_emit_request_delivered = false;
+
+static inline bool exclude_paths_to_gc_roots(int64_t cutoff_ticks) {
+ return cutoff_ticks <= _no_path_to_gc_roots;
+}
+
+static void enqueue(const JfrLeakProfilerEmitRequest& request) {
+ assert(JfrRotationLock::is_owner(), "invariant");
+ if (_queue == nullptr) {
+ _queue = new JfrLeakProfilerEmitRequestQueue(4);
+ }
+ assert(_queue != nullptr, "invariant");
+ assert(!_oom_emit_request_posted, "invariant");
+ if (request.oom) {
+ _oom_emit_request_posted = true;
+ }
+ _queue->append(request);
+}
+
+static JfrLeakProfilerEmitRequest dequeue() {
+ assert(JfrRotationLock::is_owner(), "invariant");
+ assert(_queue != nullptr, "invariant");
+ assert(_queue->is_nonempty(), "invariant");
+ const JfrLeakProfilerEmitRequest& request = _queue->first();
+ _queue->remove_at(0);
+ return request;
+}
+
+// This version of emit excludes path-to-gc-roots, i.e. it skips reference chains.
+static void emit_leakprofiler_events(bool emit_all, bool skip_bfs, JavaThread* jt) {
+ assert(jt != nullptr, "invariant");
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
+ // Take the rotation lock to exclude flush() during event emits. This is because the event emit operation
+ // also creates a number of checkpoint events. Those checkpoint events require a future typeset checkpoint
+ // event for completeness, i.e., to be generated before being flushed to a segment.
// The upcoming flush() or rotation() after event emit completes this typeset checkpoint
- // and serializes all event emit checkpoint events to the same segment.
+ // and serializes all checkpoint events to the same segment.
JfrRotationLock lock;
+ // Take the rotation lock before the thread transition, to avoid blocking safepoints.
+ if (_oom_emit_request_posted) {
+ // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError
+ // is pending or has already been completed. We are about to crash at any time now.
+ assert(CrashOnOutOfMemoryError, "invariant");
+ return;
+ }
+ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt));
+ ThreadInVMfromNative transition(jt);
+ // Since we are not requesting path-to-gc-roots, i.e., reference chains, we need not issue a VM_Operation.
+ // Therefore, we can let the requesting thread process the request directly, since it already holds the requisite lock.
+ LeakProfiler::emit_events(_no_path_to_gc_roots, emit_all, skip_bfs);
+}
+
+void JfrRecorderService::transition_and_post_leakprofiler_emit_msg(JavaThread* jt) {
+ assert(jt != nullptr, "invariant");
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);)
+ assert(!JfrRotationLock::is_owner(), "invariant");
+ // Transition to _thread_in_VM and post a synchronous message to the JFR Recorder Thread
+ // for it to process our enqueued request, which includes paths-to-gc-roots, i.e., reference chains.
+ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt));
+ ThreadInVMfromNative transition(jt);
+ _post_box.post(MSG_EMIT_LEAKP_REFCHAINS);
+}
+
+// This version of emit includes path-to-gc-roots, i.e., it includes in the request traversing of reference chains.
+// Traversing reference chains is performed as part of a VM_Operation, and we initiate it from the JFR Recorder Thread.
+// Because multiple threads can concurrently report_on_java_out_of_memory(), having them all post a synchronous JFR msg,
+// they rendezvous at a safepoint in a convenient state, ThreadBlockInVM. This mechanism prevents any thread from racing past
+// this point and begin executing VMError::report_and_die(), until at least one oom request has been delivered.
+void JfrRecorderService::emit_leakprofiler_events_paths_to_gc_roots(int64_t cutoff_ticks,
+ bool emit_all,
+ bool skip_bfs,
+ bool oom,
+ JavaThread* jt) {
+ assert(jt != nullptr, "invariant");
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);)
+ assert(!exclude_paths_to_gc_roots(cutoff_ticks), "invariant");
+
+ {
+ JfrRotationLock lock;
+ // Take the rotation lock to read and post a request for the JFR Recorder Thread.
+ if (_oom_emit_request_posted) {
+ if (!oom) {
+ // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError
+ // is pending or has already been completed. We are about to crash at any time now.
+ assert(CrashOnOutOfMemoryError, "invariant");
+ return;
+ }
+ } else {
+ assert(!_oom_emit_request_posted, "invariant");
+ JfrLeakProfilerEmitRequest request = { cutoff_ticks, emit_all, skip_bfs, oom };
+ enqueue(request);
+ }
+ }
+ JfrRecorderService service;
+ service.transition_and_post_leakprofiler_emit_msg(jt);
+}
+
+// Leakprofiler serialization request, the jdk.jfr.internal.JVM.emitOldObjectSamples() Java entry point.
+void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks,
+ bool emit_all,
+ bool skip_bfs) {
+ JavaThread* const jt = JavaThread::current();
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt);)
+ if (exclude_paths_to_gc_roots(cutoff_ticks)) {
+ ::emit_leakprofiler_events(emit_all, skip_bfs, jt);
+ return;
+ }
+ emit_leakprofiler_events_paths_to_gc_roots(cutoff_ticks, emit_all, skip_bfs, /* oom */ false, jt);
+}
+
+// Leakprofiler serialization request, the report_on_java_out_of_memory VM entry point.
+void JfrRecorderService::emit_leakprofiler_events_on_oom() {
+ assert(CrashOnOutOfMemoryError, "invariant");
+ if (EventOldObjectSample::is_enabled()) {
+ JavaThread* const jt = JavaThread::current();
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt);)
+ ThreadToNativeFromVM transition(jt);
+ emit_leakprofiler_events_paths_to_gc_roots(max_jlong, false, false, /* oom */ true, jt);
+ }
+}
+
+// The worker routine for the JFR Recorder Thread when processing MSG_EMIT_LEAKP_REFCHAINS messages.
+void JfrRecorderService::emit_leakprofiler_events() {
+ JavaThread* const jt = JavaThread::current();
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
// Take the rotation lock before the transition.
- JavaThread* current_thread = JavaThread::current();
- MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread));
- ThreadInVMfromNative transition(current_thread);
- LeakProfiler::emit_events(cutoff_ticks, emit_all, skip_bfs);
+ JfrRotationLock lock;
+ if (_oom_emit_request_delivered) {
+ // A request to emit leakprofiler events in response to CrashOnOutOfMemoryError
+ // has already been completed. We are about to crash at any time now.
+ assert(_oom_emit_request_posted, "invariant");
+ assert(CrashOnOutOfMemoryError, "invariant");
+ return;
+ }
+
+ assert(_queue->is_nonempty(), "invariant");
+
+ {
+ MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, jt));
+ ThreadInVMfromNative transition(jt);
+ while (_queue->is_nonempty()) {
+ const JfrLeakProfilerEmitRequest& request = dequeue();
+ LeakProfiler::emit_events(request.cutoff_ticks, request.emit_all, request.skip_bfs);
+ if (_oom_emit_request_posted && request.oom) {
+ assert(CrashOnOutOfMemoryError, "invariant");
+ _oom_emit_request_delivered = true;
+ break;
+ }
+ }
+ }
+
+ // If processing involved an out-of-memory request, issue an immediate flush operation.
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
+ if (_chunkwriter.is_valid() && _oom_emit_request_delivered) {
+ invoke_flush();
+ }
}
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
index e5b4500afc0..3759ff98828 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2026, 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,19 +27,23 @@
#include "jfr/utilities/jfrAllocation.hpp"
+class JavaThread;
class JfrCheckpointManager;
class JfrChunkWriter;
+class JfrPostBox;
class JfrRepository;
class JfrStackTraceRepository;
class JfrStorage;
class JfrStringPool;
class JfrRecorderService : public StackObj {
+ friend class Jfr;
friend class JfrSafepointClearVMOperation;
friend class JfrSafepointWriteVMOperation;
private:
JfrCheckpointManager& _checkpoint_manager;
JfrChunkWriter& _chunkwriter;
+ JfrPostBox& _post_box;
JfrRepository& _repository;
JfrStackTraceRepository& _stack_trace_repository;
JfrStorage& _storage;
@@ -64,6 +68,14 @@ class JfrRecorderService : public StackObj {
void invoke_safepoint_write();
void post_safepoint_write();
+ void transition_and_post_leakprofiler_emit_msg(JavaThread* jt);
+
+ static void emit_leakprofiler_events_on_oom();
+ static void emit_leakprofiler_events_paths_to_gc_roots(int64_t cutoff_ticks,
+ bool emit_all,
+ bool skip_bfs,
+ bool oom,
+ JavaThread* jt);
public:
JfrRecorderService();
void start();
@@ -72,8 +84,12 @@ class JfrRecorderService : public StackObj {
void flushpoint();
void process_full_buffers();
void evaluate_chunk_size_for_rotation();
- void emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs);
+ void emit_leakprofiler_events();
+
static bool is_recording();
+ static void emit_leakprofiler_events(int64_t cutoff_ticks,
+ bool emit_all,
+ bool skip_bfs);
};
#endif // SHARE_JFR_RECORDER_SERVICE_JFRRECORDERSERVICE_HPP
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp
index 8aeb745b35e..c63cb37e367 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026, 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,6 +45,7 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) {
#define ROTATE (msgs & (MSGBIT(MSG_ROTATE)|MSGBIT(MSG_STOP)))
#define FLUSHPOINT (msgs & (MSGBIT(MSG_FLUSHPOINT)))
#define PROCESS_FULL_BUFFERS (msgs & (MSGBIT(MSG_ROTATE)|MSGBIT(MSG_STOP)|MSGBIT(MSG_FULLBUFFER)))
+ #define LEAKPROFILER_REFCHAINS (msgs & MSGBIT(MSG_EMIT_LEAKP_REFCHAINS))
JfrPostBox& post_box = JfrRecorderThreadEntry::post_box();
log_debug(jfr, system)("Recorder thread STARTED");
@@ -71,6 +72,9 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) {
if (PROCESS_FULL_BUFFERS) {
service.process_full_buffers();
}
+ if (LEAKPROFILER_REFCHAINS) {
+ service.emit_leakprofiler_events();
+ }
// Check amount of data written to chunk already
// if it warrants asking for a new chunk.
service.evaluate_chunk_size_for_rotation();
@@ -99,5 +103,5 @@ void recorderthread_entry(JavaThread* thread, JavaThread* unused) {
#undef ROTATE
#undef FLUSHPOINT
#undef PROCESS_FULL_BUFFERS
- #undef SCAVENGE
+ #undef LEAKPROFILER_REFCHAINS
}
diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
index 291169b9aa7..037faee1b9f 100644
--- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
+++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
@@ -656,7 +656,7 @@ JfrCPUTimeTraceQueue& JfrThreadLocal::cpu_time_jfr_queue() {
}
void JfrThreadLocal::deallocate_cpu_time_jfr_queue() {
- cpu_time_jfr_queue().resize(0);
+ cpu_time_jfr_queue().set_capacity(0);
}
void JfrThreadLocal::set_do_async_processing_of_cpu_time_jfr_requests(bool wants) {
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
index 001a40f74bc..22ced5a4411 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
@@ -1207,7 +1207,7 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
// Clear the link to an old nmethod first
JVMCIObject nmethod_mirror = installed_code_handle;
- JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::ChangeReason::JVMCI_replacing_with_new_code, JVMCI_CHECK_0);
+ JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE, JVMCI_CHECK_0);
} else {
assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
}
@@ -1218,6 +1218,14 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
return result;
C2V_END
+C2V_VMENTRY_0(jobject, getInvalidationReasonDescription, (JNIEnv *env, jobject, jint invalidation_reason))
+ HandleMark hm(THREAD);
+ JNIHandleMark jni_hm(thread);
+ nmethod::InvalidationReason reason = static_cast(invalidation_reason);
+ JVMCIObject desc = JVMCIENV->create_string(nmethod::invalidation_reason_to_string(reason), JVMCI_CHECK_NULL);
+ return JVMCIENV->get_jobject(desc);
+C2V_END
+
C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
CompilerStatistics* stats = compiler->stats();
@@ -1383,7 +1391,7 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
nmethod* code = method->code();
if (code != nullptr) {
- code->make_not_entrant(nmethod::ChangeReason::JVMCI_reprofile);
+ code->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPROFILE);
}
MethodData* method_data = method->method_data();
@@ -1396,9 +1404,14 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
C2V_END
-C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize))
+C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize, jint invalidation_reason))
+ int first = static_cast(nmethod::InvalidationReason::C1_CODEPATCH);
+ int last = static_cast(nmethod::InvalidationReason::INVALIDATION_REASONS_COUNT);
+ if (invalidation_reason < first || invalidation_reason >= last) {
+ JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Invalid invalidation_reason: %d", invalidation_reason));
+ }
JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
- JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, nmethod::ChangeReason::JVMCI_invalidate_nmethod, JVMCI_CHECK);
+ JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, static_cast(invalidation_reason), JVMCI_CHECK);
C2V_END
C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
@@ -1823,7 +1836,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_
if (!fst.current()->is_compiled_frame()) {
JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
}
- fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::ChangeReason::JVMCI_materialize_virtual_object);
+ fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT);
}
Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none);
// look for the frame again as it has been updated by deopt (pc, deopt state...)
@@ -3352,6 +3365,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)},
{CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)},
{CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)},
+ {CC "getInvalidationReasonDescription", CC "(I)" STRING, FN_PTR(getInvalidationReasonDescription)},
{CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)},
{CC "resetCompilationStatistics", CC "()V", FN_PTR(resetCompilationStatistics)},
{CC "disassembleCodeBlob", CC "(" INSTALLED_CODE ")" STRING, FN_PTR(disassembleCodeBlob)},
@@ -3360,7 +3374,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getLocalVariableTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getLocalVariableTableStart)},
{CC "getLocalVariableTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getLocalVariableTableLength)},
{CC "reprofile", CC "(" HS_METHOD2 ")V", FN_PTR(reprofile)},
- {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "Z)V", FN_PTR(invalidateHotSpotNmethod)},
+ {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "ZI)V", FN_PTR(invalidateHotSpotNmethod)},
{CC "collectCounters", CC "()[J", FN_PTR(collectCounters)},
{CC "getCountersSize", CC "()I", FN_PTR(getCountersSize)},
{CC "setCountersSize", CC "(I)Z", FN_PTR(setCountersSize)},
diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp
index 8c9facf8489..fd2b1dbd6b6 100644
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp
@@ -1750,7 +1750,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c
}
-void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::ChangeReason change_reason, JVMCI_TRAPS) {
+void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS) {
if (mirror.is_null()) {
JVMCI_THROW(NullPointerException);
}
@@ -1773,7 +1773,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm
if (!deoptimize) {
// Prevent future executions of the nmethod but let current executions complete.
- nm->make_not_entrant(change_reason);
+ nm->make_not_entrant(invalidation_reason);
// Do not clear the address field here as the Java code may still
// want to later call this method with deoptimize == true. That requires
@@ -1782,7 +1782,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm
// Deoptimize the nmethod immediately.
DeoptimizationScope deopt_scope;
deopt_scope.mark(nm);
- nm->make_not_entrant(change_reason);
+ nm->make_not_entrant(invalidation_reason);
nm->make_deoptimized();
deopt_scope.deoptimize_marked();
diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp
index b7b7c8f6771..b49bba88b6b 100644
--- a/src/hotspot/share/jvmci/jvmciEnv.hpp
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp
@@ -462,7 +462,7 @@ class JVMCIEnv : public ResourceObj {
// field of `mirror` to prevent it from being called.
// If `deoptimize` is true, the nmethod is immediately deoptimized.
// The HotSpotNmethod.address field is zero upon returning.
- void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::ChangeReason change_reason, JVMCI_TRAPS);
+ void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS);
void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS);
diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
index d5fcd2aaaba..432fefe56d1 100644
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
@@ -102,6 +102,7 @@
boolean_field(HotSpotNmethod, isDefault) \
long_field(HotSpotNmethod, compileIdSnapshot) \
object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;") \
+ int_field(HotSpotNmethod, invalidationReason) \
jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
end_class \
start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode) \
diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp
index 1f10e132eff..24ea4936822 100644
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp
@@ -797,7 +797,7 @@ void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
Universe::heap()->register_nmethod(nm);
}
-void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
+void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason) {
oop nmethod_mirror = get_nmethod_mirror(nm);
if (nmethod_mirror == nullptr) {
return;
@@ -816,12 +816,20 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
+ if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) ==
+ static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) {
+ HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason));
+ }
} else if (nm->is_not_entrant()) {
// Zero the entry point so any new invocation will fail but keep
// the address link around that so that existing activations can
// be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
+ if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) ==
+ static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) {
+ HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason));
+ }
}
}
@@ -2184,7 +2192,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
tty->print_cr("Replacing method %s", method_name);
}
if (old != nullptr) {
- old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method);
+ old->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE);
}
LogTarget(Info, nmethod, install) lt;
diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp
index b49e09a1884..95c7d32f928 100644
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp
@@ -121,7 +121,7 @@ class JVMCINMethodData : public ResourceObj {
// Clears the HotSpotNmethod.address field in the mirror. If nm
// is dead, the HotSpotNmethod.entryPoint field is also cleared.
- void invalidate_nmethod_mirror(nmethod* nm);
+ void invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason);
// Gets the mirror from nm's oops table.
oop get_nmethod_mirror(nmethod* nm);
diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
index e26c815946d..eb2843008fd 100644
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
@@ -564,7 +564,30 @@
declare_constant_with_value("LockStack::_end_offset", LockStack::end_offset()) \
declare_constant_with_value("OMCache::oop_to_oop_difference", OMCache::oop_to_oop_difference()) \
declare_constant_with_value("OMCache::oop_to_monitor_difference", OMCache::oop_to_monitor_difference()) \
- \
+ \
+ declare_constant(nmethod::InvalidationReason::NOT_INVALIDATED) \
+ declare_constant(nmethod::InvalidationReason::C1_CODEPATCH) \
+ declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE) \
+ declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING) \
+ declare_constant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP) \
+ declare_constant(nmethod::InvalidationReason::CI_REPLAY) \
+ declare_constant(nmethod::InvalidationReason::UNLOADING) \
+ declare_constant(nmethod::InvalidationReason::UNLOADING_COLD) \
+ declare_constant(nmethod::InvalidationReason::JVMCI_INVALIDATE) \
+ declare_constant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT) \
+ declare_constant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE) \
+ declare_constant(nmethod::InvalidationReason::JVMCI_REPROFILE) \
+ declare_constant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION) \
+ declare_constant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER) \
+ declare_constant(nmethod::InvalidationReason::NOT_USED) \
+ declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH) \
+ declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1) \
+ declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL) \
+ declare_constant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION) \
+ declare_constant(nmethod::InvalidationReason::UNCOMMON_TRAP) \
+ declare_constant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION) \
+ declare_constant(nmethod::InvalidationReason::ZOMBIE) \
+ \
declare_constant(CodeInstaller::VERIFIED_ENTRY) \
declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \
declare_constant(CodeInstaller::OSR_ENTRY) \
@@ -809,7 +832,6 @@
\
AARCH64_ONLY(declare_constant(NMethodPatchingType::stw_instruction_and_data_patch)) \
AARCH64_ONLY(declare_constant(NMethodPatchingType::conc_instruction_and_data_patch)) \
- AARCH64_ONLY(declare_constant(NMethodPatchingType::conc_data_patch)) \
\
declare_constant(ObjectMonitor::NO_OWNER) \
declare_constant(ObjectMonitor::ANONYMOUS_OWNER) \
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
index 6cb8c4244d9..dd15294c3cf 100644
--- a/src/hotspot/share/oops/instanceKlass.cpp
+++ b/src/hotspot/share/oops/instanceKlass.cpp
@@ -312,12 +312,11 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) {
ss.print("Nest host resolution of %s with host %s failed: ",
this->external_name(), target_host_class);
java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
- const char* msg = ss.as_string(true /* on C-heap */);
constantPoolHandle cph(THREAD, constants());
- SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg);
+ SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss);
CLEAR_PENDING_EXCEPTION;
- log_trace(class, nestmates)("%s", msg);
+ log_trace(class, nestmates)("%s", ss.base());
} else {
// A valid nest-host is an instance class in the current package that lists this
// class as a nest member. If any of these conditions are not met the class is
@@ -356,10 +355,9 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) {
k->external_name(),
k->class_loader_data()->loader_name_and_id(),
error);
- const char* msg = ss.as_string(true /* on C-heap */);
constantPoolHandle cph(THREAD, constants());
- SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg);
- log_trace(class, nestmates)("%s", msg);
+ SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss);
+ log_trace(class, nestmates)("%s", ss.base());
}
}
} else {
@@ -3495,7 +3493,7 @@ void InstanceKlass::add_osr_nmethod(nmethod* n) {
for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true);
if (inv != nullptr && inv->is_in_use()) {
- inv->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_of_lower_level);
+ inv->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL);
}
}
}
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
index 1a36fce23aa..bb7a0576eec 100644
--- a/src/hotspot/share/oops/method.cpp
+++ b/src/hotspot/share/oops/method.cpp
@@ -1028,7 +1028,7 @@ void Method::set_native_function(address function, bool post_event_flag) {
// If so, we have to make it not_entrant.
nmethod* nm = code(); // Put it into local variable to guard against concurrent updates
if (nm != nullptr) {
- nm->make_not_entrant(nmethod::ChangeReason::set_native_function);
+ nm->make_not_entrant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION);
}
}
diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp
index 143398c57d0..4f8590082cd 100644
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -1425,8 +1425,10 @@ static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
Node* x = add2->in(1);
Node* con2 = add2->in(2);
if (is_sub_con(con2)) {
+ // The graph could be dying (i.e. x is top) in which case type(x) is not a long.
+ const TypeLong* x_long = phase->type(x)->isa_long();
// Collapsed graph not equivalent if potential over/underflow -> bailing out (*)
- if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) {
+ if (x_long == nullptr || can_overflow(x_long, con1->get_long() + con2->get_long())) {
return nullptr;
}
Node* new_con = phase->transform(new AddLNode(con1, con2));
diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp
index e14d63c7651..30368d80ca9 100644
--- a/src/hotspot/share/opto/chaitin.cpp
+++ b/src/hotspot/share/opto/chaitin.cpp
@@ -2375,7 +2375,7 @@ void PhaseChaitin::dump_frame() const {
tty->print_cr("saved fp register");
else if (return_addr == OptoReg::add(reg, 2*VMRegImpl::slots_per_word) &&
VerifyStackAtCalls)
- tty->print_cr("0xBADB100D +VerifyStackAtCalls");
+ tty->print_cr(" +VerifyStackAtCalls");
else
tty->print_cr("in_preserve");
} else if ((int)OptoReg::reg2stack(reg) < fixed_slots) {
diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp
index c6ed2411fe3..99fedcdf880 100644
--- a/src/hotspot/share/opto/macro.cpp
+++ b/src/hotspot/share/opto/macro.cpp
@@ -606,6 +606,11 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode
for (DUIterator_Fast kmax, k = use->fast_outs(kmax);
k < kmax && can_eliminate; k++) {
Node* n = use->fast_out(k);
+ if (n->is_Mem() && n->as_Mem()->is_mismatched_access()) {
+ DEBUG_ONLY(disq_node = n);
+ NOT_PRODUCT(fail_eliminate = "Mismatched access");
+ can_eliminate = false;
+ }
if (!n->is_Store() && n->Opcode() != Op_CastP2X && !bs->is_gc_pre_barrier_node(n) && !reduce_merge_precheck) {
DEBUG_ONLY(disq_node = n;)
if (n->is_Load() || n->is_LoadStore()) {
@@ -743,6 +748,41 @@ void PhaseMacroExpand::undo_previous_scalarizations(GrowableArray basic_type();
+ BasicType field_bt = field_type->basic_type();
+
+ // Primitive types must match.
+ if (is_java_primitive(value_bt) && value_bt == field_bt) { return; }
+
+ // I have been struggling to make a similar assert for non-primitive
+ // types. I we can add one in the future. For now, I just let them
+ // pass without checks.
+ // In particular, I was struggling with a value that came from a call,
+ // and had only a non-null check CastPP. There was also a checkcast
+ // in the graph to verify the interface, but the corresponding
+ // CheckCastPP result was not updated in the stack slot, and so
+ // we ended up using the CastPP. That means that the field knows
+ // that it should get an oop from an interface, but the value lost
+ // that information, and so it is not a subtype.
+ // There may be other issues, feel free to investigate further!
+ if (!is_java_primitive(value_bt)) { return; }
+
+ tty->print_cr("value not compatible for field: %s vs %s",
+ type2name(value_bt),
+ type2name(field_bt));
+ tty->print("value_type: ");
+ value_type->dump();
+ tty->cr();
+ tty->print("field_type: ");
+ field_type->dump();
+ tty->cr();
+ assert(false, "value_type does not fit field_type");
+ }
+#endif
+
SafePointScalarObjectNode* PhaseMacroExpand::create_scalarized_object_description(AllocateNode *alloc, SafePointNode* sfpt) {
// Fields of scalar objs are referenced only at the end
// of regular debuginfo at the last (youngest) JVMS.
@@ -859,6 +899,7 @@ SafePointScalarObjectNode* PhaseMacroExpand::create_scalarized_object_descriptio
field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type()));
}
}
+ DEBUG_ONLY(verify_type_compatability(field_val->bottom_type(), field_type);)
sfpt->add_req(field_val);
}
diff --git a/src/hotspot/share/prims/jvmtiAgentList.cpp b/src/hotspot/share/prims/jvmtiAgentList.cpp
index a4b7606056d..6a9c62babe5 100644
--- a/src/hotspot/share/prims/jvmtiAgentList.cpp
+++ b/src/hotspot/share/prims/jvmtiAgentList.cpp
@@ -201,6 +201,11 @@ void JvmtiAgentList::load_xrun_agents() {
// Invokes Agent_OnAttach for agents loaded dynamically during runtime.
void JvmtiAgentList::load_agent(const char* agent_name, bool is_absolute_path,
const char* options, outputStream* st) {
+ if (JvmtiEnvBase::get_phase() != JVMTI_PHASE_LIVE) {
+ st->print_cr("Dynamic agent loading is only permitted in the live phase");
+ return;
+ }
+
JvmtiAgent* const agent = new JvmtiAgent(agent_name, options, is_absolute_path, /* dynamic agent */ true);
if (agent->load(st)) {
add(agent);
diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp
index facbaaf9ad0..bf8df8acf3b 100644
--- a/src/hotspot/share/prims/jvmtiEventController.cpp
+++ b/src/hotspot/share/prims/jvmtiEventController.cpp
@@ -785,9 +785,6 @@ void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env,
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
EC_TRACE(("[*] # set event callbacks"));
- // May be changing the event handler for ObjectFree.
- flush_object_free_events(env);
-
env->set_event_callbacks(callbacks, size_of_callbacks);
jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits();
@@ -1097,6 +1094,8 @@ JvmtiEventController::set_event_callbacks(JvmtiEnvBase *env,
// call the functionality without holding the JvmtiThreadState_lock.
JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks);
} else {
+ JvmtiEventControllerPrivate::flush_object_free_events(env);
+
MutexLocker mu(JvmtiThreadState_lock);
JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks);
}
@@ -1184,6 +1183,8 @@ JvmtiEventController::env_dispose(JvmtiEnvBase *env) {
// call the functionality without holding the JvmtiThreadState_lock.
JvmtiEventControllerPrivate::env_dispose(env);
} else {
+ JvmtiEventControllerPrivate::flush_object_free_events(env);
+
MutexLocker mu(JvmtiThreadState_lock);
JvmtiEventControllerPrivate::env_dispose(env);
}
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index 0041bf68729..c84bef57e9b 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -46,6 +46,7 @@
#include "gc/shared/concurrentGCBreakpoints.hpp"
#include "gc/shared/gcConfig.hpp"
#include "gc/shared/genArguments.hpp"
+#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jvm.h"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "logging/log.hpp"
@@ -195,6 +196,10 @@ WB_ENTRY(jint, WB_TakeLockAndHangInSafepoint(JNIEnv* env, jobject wb))
return 0;
WB_END
+WB_ENTRY(jlong, WB_GetMinimumJavaStackSize(JNIEnv* env, jobject o))
+ return os::get_minimum_java_stack_size();
+WB_END
+
class WBIsKlassAliveClosure : public LockedClassesDo {
Symbol* _name;
int _count;
@@ -504,6 +509,14 @@ WB_ENTRY(jboolean, WB_ConcurrentGCRunTo(JNIEnv* env, jobject o, jobject at))
return ConcurrentGCBreakpoints::run_to(c_name);
WB_END
+WB_ENTRY(jboolean, WB_HasExternalSymbolsStripped(JNIEnv* env, jobject o))
+#if defined(HAS_STRIPPED_DEBUGINFO)
+ return true;
+#else
+ return false;
+#endif
+WB_END
+
#if INCLUDE_G1GC
WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
@@ -794,7 +807,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
if (_make_not_entrant) {
nmethod* nm = CodeCache::find_nmethod(f->pc());
assert(nm != nullptr, "did not find nmethod");
- nm->make_not_entrant(nmethod::ChangeReason::whitebox_deoptimization);
+ nm->make_not_entrant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION);
}
++_result;
}
@@ -2683,6 +2696,32 @@ WB_ENTRY(void, WB_WaitUnsafe(JNIEnv* env, jobject wb, jint time))
os::naked_short_sleep(time);
WB_END
+WB_ENTRY(void, WB_BusyWait(JNIEnv* env, jobject wb, jint time))
+ ThreadToNativeFromVM ttn(thread);
+ u8 start = os::current_thread_cpu_time();
+ u8 target_duration = time * (u8)1000000;
+ while (os::current_thread_cpu_time() - start < target_duration) {
+ for (volatile int i = 0; i < 1000000; i++);
+ }
+WB_END
+
+WB_ENTRY(jboolean, WB_CPUSamplerSetOutOfStackWalking(JNIEnv* env, jobject wb, jboolean enable))
+ #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX)
+ JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(enable == JNI_TRUE);
+ return JNI_TRUE;
+ #else
+ return JNI_FALSE;
+ #endif
+WB_END
+
+WB_ENTRY(jlong, WB_CPUSamplerOutOfStackWalkingIterations(JNIEnv* env, jobject wb))
+ #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX)
+ return (jlong)JfrCPUTimeThreadSampling::out_of_stack_walking_iterations();
+ #else
+ return 0;
+ #endif
+WB_END
+
WB_ENTRY(jstring, WB_GetLibcName(JNIEnv* env, jobject o))
ThreadToNativeFromVM ttn(thread);
jstring info_string = env->NewStringUTF(XSTR(LIBC));
@@ -2761,6 +2800,7 @@ static JNINativeMethod methods[] = {
{CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize},
{CC"getHeapSpaceAlignment", CC"()J", (void*)&WB_GetHeapSpaceAlignment},
{CC"getHeapAlignment", CC"()J", (void*)&WB_GetHeapAlignment},
+ {CC"hasExternalSymbolsStripped", CC"()Z", (void*)&WB_HasExternalSymbolsStripped},
{CC"countAliveClasses0", CC"(Ljava/lang/String;)I", (void*)&WB_CountAliveClasses },
{CC"getSymbolRefcount", CC"(Ljava/lang/String;)I", (void*)&WB_GetSymbolRefcount },
{CC"parseCommandLine0",
@@ -3032,6 +3072,9 @@ static JNINativeMethod methods[] = {
{CC"isJVMTIIncluded", CC"()Z", (void*)&WB_IsJVMTIIncluded},
{CC"waitUnsafe", CC"(I)V", (void*)&WB_WaitUnsafe},
+ {CC"busyWait", CC"(I)V", (void*)&WB_BusyWait},
+ {CC"cpuSamplerSetOutOfStackWalking", CC"(Z)Z", (void*)&WB_CPUSamplerSetOutOfStackWalking},
+ {CC"cpuSamplerOutOfStackWalkingIterations", CC"()J",(void*)&WB_CPUSamplerOutOfStackWalkingIterations},
{CC"getLibcName", CC"()Ljava/lang/String;", (void*)&WB_GetLibcName},
{CC"pinObject", CC"(Ljava/lang/Object;)V", (void*)&WB_PinObject},
@@ -3041,7 +3084,8 @@ static JNINativeMethod methods[] = {
{CC"cleanMetaspaces", CC"()V", (void*)&WB_CleanMetaspaces},
{CC"rss", CC"()J", (void*)&WB_Rss},
{CC"printString", CC"(Ljava/lang/String;I)Ljava/lang/String;", (void*)&WB_PrintString},
- {CC"lockAndStuckInSafepoint", CC"()V", (void*)&WB_TakeLockAndHangInSafepoint},
+ {CC"lockAndStuckInSafepoint", CC"()V", (void*)&WB_TakeLockAndHangInSafepoint},
+ {CC"getMinimumJavaStackSize", CC"()J", (void*)&WB_GetMinimumJavaStackSize},
{CC"wordSize", CC"()J", (void*)&WB_WordSize},
{CC"rootChunkWordSize", CC"()J", (void*)&WB_RootChunkWordSize},
{CC"isStatic", CC"()Z", (void*)&WB_IsStaticallyLinked}
diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp
index 1d1a7699c50..6012b87e50b 100644
--- a/src/hotspot/share/runtime/abstract_vm_version.cpp
+++ b/src/hotspot/share/runtime/abstract_vm_version.cpp
@@ -283,6 +283,8 @@ const char* Abstract_VM_Version::internal_vm_info_string() {
#define HOTSPOT_BUILD_COMPILER "MS VC++ 17.13 (VS2022)"
#elif _MSC_VER == 1944
#define HOTSPOT_BUILD_COMPILER "MS VC++ 17.14 (VS2022)"
+ #elif _MSC_VER == 1950
+ #define HOTSPOT_BUILD_COMPILER "MS VC++ 18.0 (VS2026)"
#else
#define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER)
#endif
diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp
index 3c8532b9e87..a9f37bddb43 100644
--- a/src/hotspot/share/runtime/continuationEntry.hpp
+++ b/src/hotspot/share/runtime/continuationEntry.hpp
@@ -39,6 +39,7 @@ class RegisterMap;
// Metadata stored in the continuation entry frame
class ContinuationEntry {
+ friend class VMStructs;
friend class JVMCIVMStructs;
ContinuationEntryPD _pd;
#ifdef ASSERT
diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp
index a0d9dd00339..63de5e6d37a 100644
--- a/src/hotspot/share/runtime/deoptimization.cpp
+++ b/src/hotspot/share/runtime/deoptimization.cpp
@@ -1382,6 +1382,9 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
case T_INT: case T_FLOAT: { // 4 bytes.
assert(value->type() == T_INT, "Agreement.");
+#if INCLUDE_JVMCI
+ // big_value allows encoding double/long value as e.g. [int = 0, long], and storing
+ // the value in two array elements.
bool big_value = false;
if (i + 1 < sv->field_size() && type == T_INT) {
if (sv->field_at(i)->is_location()) {
@@ -1409,6 +1412,9 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
} else {
obj->int_at_put(index, value->get_jint());
}
+#else // not INCLUDE_JVMCI
+ obj->int_at_put(index, value->get_jint());
+#endif // INCLUDE_JVMCI
break;
}
@@ -1826,7 +1832,7 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason
#if INCLUDE_JVMCI
address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) {
// there is no exception handler for this pc => deoptimize
- nm->make_not_entrant(nmethod::ChangeReason::missing_exception_handler);
+ nm->make_not_entrant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER);
// Use Deoptimization::deoptimize for all of its side-effects:
// gathering traps statistics, logging...
@@ -2455,7 +2461,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
// Recompile
if (make_not_entrant) {
- if (!nm->make_not_entrant(nmethod::ChangeReason::uncommon_trap)) {
+ if (!nm->make_not_entrant(nmethod::InvalidationReason::UNCOMMON_TRAP)) {
return; // the call did not change nmethod's state
}
diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp
index 497420c8502..83280c1f9f1 100644
--- a/src/hotspot/share/runtime/java.cpp
+++ b/src/hotspot/share/runtime/java.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2026, 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
@@ -463,10 +463,7 @@ void before_exit(JavaThread* thread, bool halt) {
event.commit();
}
- // 2nd argument (emit_event_shutdown) should be set to false
- // because EventShutdown would be emitted at Threads::destroy_vm().
- // (one of the callers of before_exit())
- JFR_ONLY(Jfr::on_vm_shutdown(true, false, halt);)
+ JFR_ONLY(Jfr::on_vm_shutdown(false, halt);)
// Stop the WatcherThread. We do this before disenrolling various
// PeriodicTasks to reduce the likelihood of races.
diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp
index fcb068ec8fa..20de4beebdd 100644
--- a/src/hotspot/share/runtime/javaThread.cpp
+++ b/src/hotspot/share/runtime/javaThread.cpp
@@ -1339,7 +1339,7 @@ void JavaThread::make_zombies() {
// it is a Java nmethod
nmethod* nm = CodeCache::find_nmethod(fst.current()->pc());
assert(nm != nullptr, "did not find nmethod");
- nm->make_not_entrant(nmethod::ChangeReason::zombie);
+ nm->make_not_entrant(nmethod::InvalidationReason::ZOMBIE);
}
}
}
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 8278abb73e2..1e1f8e90be6 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -2573,6 +2573,10 @@ jint os::set_minimum_stack_sizes() {
return JNI_OK;
}
+jlong os::get_minimum_java_stack_size() {
+ return static_cast(_java_thread_min_stack_allowed);
+}
+
// Builds a platform dependent Agent_OnLoad_ function name
// which is used to find statically linked in agents.
// Parameters:
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index b26ec280e72..bb07abad6b1 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -397,6 +397,8 @@ class os: AllStatic {
static jint set_minimum_stack_sizes();
public:
+ // get allowed minimum java stack size
+ static jlong get_minimum_java_stack_size();
// Find committed memory region within specified range (start, start + size),
// return true if found any
static bool committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size);
diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp
index 9c710fc98e4..b9610064c13 100644
--- a/src/hotspot/share/runtime/sharedRuntime.cpp
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp
@@ -3364,7 +3364,7 @@ JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *current) )
RegisterMap::WalkContinuation::skip);
frame sender = fr.sender(&map);
if (sender.is_interpreted_frame()) {
- current->push_cont_fastpath(sender.sp());
+ current->push_cont_fastpath(sender.unextended_sp());
}
return buf;
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index 4f5dfd474ba..879a2324e54 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -624,6 +624,7 @@
nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \
nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \
volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \
+ nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \
nonstatic_field(Thread, _osthread, OSThread*) \
\
/************/ \
@@ -806,7 +807,8 @@
nonstatic_field(Mutex, _name, const char*) \
static_field(Mutex, _mutex_array, Mutex**) \
static_field(Mutex, _num_mutex, int) \
- volatile_nonstatic_field(Mutex, _owner, Thread*)
+ volatile_nonstatic_field(Mutex, _owner, Thread*) \
+ static_field(ContinuationEntry, _return_pc, address)
//--------------------------------------------------------------------------------
// VM_TYPES
@@ -1280,6 +1282,7 @@
declare_toplevel_type(FileMapHeader) \
declare_toplevel_type(CDSFileMapRegion) \
declare_toplevel_type(UpcallStub::FrameData) \
+ declare_toplevel_type(ContinuationEntry) \
\
/************/ \
/* GC types */ \
diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp
index abe3d6757b5..bd5adc7acf9 100644
--- a/src/hotspot/share/utilities/debug.cpp
+++ b/src/hotspot/share/utilities/debug.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2026, 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
@@ -63,12 +63,17 @@
#include "utilities/nativeStackPrinter.hpp"
#include "utilities/unsigned5.hpp"
#include "utilities/vmError.hpp"
+#if INCLUDE_JFR
+#include "jfr/jfr.hpp"
+#endif
#include
#include
-// These functions needs to be exported on Windows only
-#define DEBUGEXPORT WINDOWS_ONLY(JNIEXPORT)
+// These functions needs to be exported on Windows
+// On Linux it is also beneficial to export them to avoid
+// losing them e.g. with linktime gc
+#define DEBUGEXPORT JNIEXPORT
// Support for showing register content on asserts/guarantees.
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
@@ -262,6 +267,8 @@ void report_untested(const char* file, int line, const char* message) {
void report_java_out_of_memory(const char* message) {
static int out_of_memory_reported = 0;
+ JFR_ONLY(Jfr::on_report_java_out_of_memory();)
+
// A number of threads may attempt to report OutOfMemoryError at around the
// same time. To avoid dumping the heap or executing the data collection
// commands multiple times we just do it once when the first threads reports
@@ -610,36 +617,60 @@ extern "C" DEBUGEXPORT intptr_t u5p(intptr_t addr,
void pp(intptr_t p) { pp((void*)p); }
void pp(oop p) { pp((void*)p); }
-void help() {
+extern "C" DEBUGEXPORT void help() {
Command c("help");
tty->print_cr("basic");
- tty->print_cr(" pp(void* p) - try to make sense of p");
- tty->print_cr(" ps() - print current thread stack");
- tty->print_cr(" pss() - print all thread stacks");
- tty->print_cr(" pm(int pc) - print Method* given compiled PC");
- tty->print_cr(" findm(intptr_t pc) - finds Method*");
- tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
- tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g.");
- tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 or");
- tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or");
- tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64 or");
- tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or");
- tty->print_cr(" pns($sp, $s8, $pc) on Linux/mips or");
- tty->print_cr(" pns($sp, $fp, $pc) on Linux/RISC-V");
+ tty->print_cr(" pp(void* p) - try to make sense of p");
+ tty->print_cr(" ps() - print current thread stack");
+ tty->print_cr(" pss() - print all thread stacks");
+ tty->print_cr(" findnm(intptr_t pc) - find nmethod*");
+ tty->print_cr(" findm(intptr_t pc) - find Method*");
+ tty->print_cr(" find(intptr_t x) - find & print nmethod/stub/bytecode/oop based on pointer into it");
+ tty->print_cr(" findpc(intptr_t x) - find & print nmethod/stub/bytecode/oop based on pointer into it (verbose)");
+
+#ifndef PRODUCT
+ tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace, e.g.");
+#ifdef LINUX
+ AMD64_ONLY( tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64"));
+ IA32_ONLY( tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86"));
+ AARCH64_ONLY(tty->print_cr(" pns($sp, $fp, $pc) on Linux/AArch64"));
+ RISCV_ONLY( tty->print_cr(" pns($sp, $fp, $pc) on Linux/RISC-V"));
+ PPC64_ONLY( tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64"));
+#endif // LINUX
tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()");
tty->print_cr(" - in dbx do 'frame 1' before calling pns()");
+#endif // !PRODUCT
+
+ tty->print_cr("universe.");
+ tty->print_cr(" verify(intptr_t p) - run verify on Universe");
+ tty->print_cr(" threads() - print all threads");
+ tty->print_cr(" psd() - print system dictionary");
+
tty->print_cr("class metadata.");
tty->print_cr(" findclass(name_pattern, flags)");
tty->print_cr(" findmethod(class_name_pattern, method_pattern, flags)");
- tty->print_cr("misc.");
- tty->print_cr(" flush() - flushes the log file");
- tty->print_cr(" events() - dump events from ring buffers");
+ tty->print_cr("method metadata.");
+ tty->print_cr(" blob(CodeBlob* p) - print CodeBlob");
+ tty->print_cr(" dump_vtable(address p) - dump vtable of the Klass");
+ tty->print_cr(" nm(intptr_t p) - find & print CodeBlob details");
+ tty->print_cr(" disnm(intptr_t p) - find & print disassembly of CodeBlob");
+ tty->print_cr(" printnm(intptr_t p) - print nmethod details");
+ tty->print_cr(" findbcp(method, bcp) - find & prints bcp");
+ tty->print_cr("stack frame details.");
+ tty->print_cr(" pfl() - print frame layout");
+ tty->print_cr(" psf() - print stack frames");
+
+ tty->print_cr("misc.");
+ tty->print_cr(" flush() - flush the log file");
+ tty->print_cr(" events() - dump events from ring buffers");
+ tty->print_cr(" u5decode(intptr_t addr) - decode a single u5 value");
+ tty->print_cr(" u5p(intptr_t addr, intptr_t limit, int count) - decode u5 values");
tty->print_cr("compiler debugging");
- tty->print_cr(" debug() - to set things up for compiler debugging");
- tty->print_cr(" ndebug() - undo debug");
+ tty->print_cr(" debug() - set things up for compiler debugging");
+ tty->print_cr(" ndebug() - undo debug");
}
#ifndef PRODUCT
diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp
index d33387e516e..93ae435ae72 100644
--- a/src/hotspot/share/utilities/vmError.cpp
+++ b/src/hotspot/share/utilities/vmError.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024 SAP SE. All rights reserved.
* Copyright (c) 2023, 2025, Red Hat, Inc. and/or its affiliates.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -1857,7 +1857,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
log.set_fd(-1);
}
- JFR_ONLY(Jfr::on_vm_shutdown(static_cast(_id) == OOM_JAVA_HEAP_FATAL, true);)
+ JFR_ONLY(Jfr::on_vm_shutdown(true, false, static_cast(_id) == OOM_JAVA_HEAP_FATAL);)
if (PrintNMTStatistics) {
fdStream fds(fd_out);
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java b/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java
new file mode 100644
index 00000000000..c0fd9ffa599
--- /dev/null
+++ b/src/java.base/share/classes/com/sun/crypto/provider/RSACipherAdaptor.java
@@ -0,0 +1,146 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.crypto.provider;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureSpi;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+/**
+ * NONEwithRSA Signature implementation using the RSA/ECB/PKCS1Padding Cipher
+ * implementation from SunJCE.
+ */
+public final class RSACipherAdaptor extends SignatureSpi {
+
+ private final RSACipher c;
+ private ByteArrayOutputStream verifyBuf;
+
+ public RSACipherAdaptor() {
+ c = new RSACipher();
+ }
+
+ @Override
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.DECRYPT_MODE, publicKey, null);
+ if (verifyBuf == null) {
+ verifyBuf = new ByteArrayOutputStream(128);
+ } else {
+ verifyBuf.reset();
+ }
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.ENCRYPT_MODE, privateKey, null);
+ verifyBuf = null;
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.ENCRYPT_MODE, privateKey, random);
+ verifyBuf = null;
+ }
+
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ engineUpdate(new byte[] {b}, 0, 1);
+ }
+
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ if (verifyBuf != null) {
+ verifyBuf.write(b, off, len);
+ } else {
+ byte[] out = c.engineUpdate(b, off, len);
+ if ((out != null) && (out.length != 0)) {
+ throw new SignatureException
+ ("Cipher unexpectedly returned data");
+ }
+ }
+ }
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ try {
+ return c.engineDoFinal(null, 0, 0);
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ try {
+ byte[] out = c.engineDoFinal(sigBytes, 0, sigBytes.length);
+ byte[] data = verifyBuf.toByteArray();
+ verifyBuf.reset();
+ return MessageDigest.isEqual(out, data);
+ } catch (BadPaddingException e) {
+ // e.g. wrong public key used
+ // return false rather than throwing exception
+ return false;
+ } catch (IllegalBlockSizeException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ @Override
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ if (params != null) {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
index cc99464dff3..22d5f17c6e0 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
@@ -136,6 +136,12 @@ public SunJCE() {
void putEntries() {
// reuse attribute map and reset before each reuse
HashMap attrs = new HashMap<>(3);
+ attrs.put("SupportedKeyClasses",
+ "java.security.interfaces.RSAPublicKey" +
+ "|java.security.interfaces.RSAPrivateKey");
+ ps("Signature", "NONEwithRSA",
+ "com.sun.crypto.provider.RSACipherAdaptor", null, attrs);
+ // continue adding cipher specific attributes
attrs.put("SupportedModes", "ECB");
attrs.put("SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPPADDING"
+ "|OAEPWITHMD5ANDMGF1PADDING"
@@ -147,9 +153,6 @@ void putEntries() {
+ "|OAEPWITHSHA-512ANDMGF1PADDING"
+ "|OAEPWITHSHA-512/224ANDMGF1PADDING"
+ "|OAEPWITHSHA-512/256ANDMGF1PADDING");
- attrs.put("SupportedKeyClasses",
- "java.security.interfaces.RSAPublicKey" +
- "|java.security.interfaces.RSAPrivateKey");
ps("Cipher", "RSA",
"com.sun.crypto.provider.RSACipher", null, attrs);
diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java
index cedb6124a31..c9c47666bf0 100644
--- a/src/java.base/share/classes/java/io/Console.java
+++ b/src/java.base/share/classes/java/io/Console.java
@@ -25,6 +25,7 @@
package java.io;
+import java.lang.annotation.Native;
import java.util.*;
import java.nio.charset.Charset;
import jdk.internal.access.JavaIOAccess;
@@ -545,7 +546,7 @@ public Charset charset() {
* @since 22
*/
public boolean isTerminal() {
- return istty;
+ return isStdinTty() && isStdoutTty();
}
private static UnsupportedOperationException newUnsupportedOperationException() {
@@ -553,7 +554,12 @@ private static UnsupportedOperationException newUnsupportedOperationException()
"Console class itself does not provide implementation");
}
- private static final boolean istty = istty();
+ @Native static final int TTY_STDIN_MASK = 0x00000001;
+ @Native static final int TTY_STDOUT_MASK = 0x00000002;
+ @Native static final int TTY_STDERR_MASK = 0x00000004;
+ // ttyStatus() returns bit patterns above, a bit is set if the corresponding file
+ // descriptor is a character device
+ private static final int ttyStatus = ttyStatus();
private static final Charset STDIN_CHARSET =
Charset.forName(System.getProperty("stdin.encoding"), UTF_8.INSTANCE);
private static final Charset STDOUT_CHARSET =
@@ -565,6 +571,9 @@ private static UnsupportedOperationException newUnsupportedOperationException()
public Console console() {
return cons;
}
+ public boolean isStdinTty() {
+ return Console.isStdinTty();
+ }
});
}
@@ -586,7 +595,7 @@ private static Console instantiateConsole() {
for (var jcp : ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class)) {
if (consModName.equals(jcp.getClass().getModule().getName())) {
- var jc = jcp.console(istty, STDIN_CHARSET, STDOUT_CHARSET);
+ var jc = jcp.console(isStdinTty() && isStdoutTty(), STDIN_CHARSET, STDOUT_CHARSET);
if (jc != null) {
c = new ProxyingConsole(jc);
}
@@ -597,12 +606,21 @@ private static Console instantiateConsole() {
}
// If not found, default to built-in Console
- if (istty && c == null) {
+ if (isStdinTty() && isStdoutTty() && c == null) {
c = new ProxyingConsole(new JdkConsoleImpl(STDIN_CHARSET, STDOUT_CHARSET));
}
return c;
}
- private static native boolean istty();
+ private static boolean isStdinTty() {
+ return (ttyStatus & TTY_STDIN_MASK) != 0;
+ }
+ private static boolean isStdoutTty() {
+ return (ttyStatus & TTY_STDOUT_MASK) != 0;
+ }
+ private static boolean isStderrTty() {
+ return (ttyStatus & TTY_STDERR_MASK) != 0;
+ }
+ private static native int ttyStatus();
}
diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java
index bcdbc39e665..bc42aa8a9fe 100644
--- a/src/java.base/share/classes/java/lang/System.java
+++ b/src/java.base/share/classes/java/lang/System.java
@@ -238,10 +238,11 @@ public static void setErr(PrintStream err) {
private static volatile Console cons;
/**
- * Returns the unique {@link java.io.Console Console} object associated
+ * Returns the unique {@link Console Console} object associated
* with the current Java virtual machine, if any.
*
* @return The system console, if any, otherwise {@code null}.
+ * @see Console
*
* @since 1.6
*/
diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java
index 19465eb32db..b0b134e69a3 100644
--- a/src/java.base/share/classes/java/lang/VirtualThread.java
+++ b/src/java.base/share/classes/java/lang/VirtualThread.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, 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
@@ -89,15 +89,19 @@ final class VirtualThread extends BaseVirtualThread {
*
* RUNNING -> PARKING // Thread parking with LockSupport.park
* PARKING -> PARKED // cont.yield successful, parked indefinitely
- * PARKING -> PINNED // cont.yield failed, parked indefinitely on carrier
* PARKED -> UNPARKED // unparked, may be scheduled to continue
- * PINNED -> RUNNING // unparked, continue execution on same carrier
* UNPARKED -> RUNNING // continue execution after park
*
+ * PARKING -> RUNNING // cont.yield failed, need to park on carrier
+ * RUNNING -> PINNED // park on carrier
+ * PINNED -> RUNNING // unparked, continue execution on same carrier
+ *
* RUNNING -> TIMED_PARKING // Thread parking with LockSupport.parkNanos
* TIMED_PARKING -> TIMED_PARKED // cont.yield successful, timed-parked
- * TIMED_PARKING -> TIMED_PINNED // cont.yield failed, timed-parked on carrier
* TIMED_PARKED -> UNPARKED // unparked, may be scheduled to continue
+ *
+ * TIMED_PARKING -> RUNNING // cont.yield failed, need to park on carrier
+ * RUNNING -> TIMED_PINNED // park on carrier
* TIMED_PINNED -> RUNNING // unparked, continue execution on same carrier
*
* RUNNING -> BLOCKING // blocking on monitor enter
@@ -108,7 +112,7 @@ final class VirtualThread extends BaseVirtualThread {
* RUNNING -> WAITING // transitional state during wait on monitor
* WAITING -> WAIT // waiting on monitor
* WAIT -> BLOCKED // notified, waiting to be unblocked by monitor owner
- * WAIT -> UNBLOCKED // timed-out/interrupted
+ * WAIT -> UNBLOCKED // interrupted
*
* RUNNING -> TIMED_WAITING // transition state during timed-waiting on monitor
* TIMED_WAITING -> TIMED_WAIT // timed-waiting on monitor
@@ -838,16 +842,20 @@ private void parkOnCarrierThread(boolean timed, long nanos) {
* Re-enables this virtual thread for scheduling. If this virtual thread is parked
* then its task is scheduled to continue, otherwise its next call to {@code park} or
* {@linkplain #parkNanos(long) parkNanos} is guaranteed not to block.
+ * @param lazySubmit to use lazySubmit if possible
* @throws RejectedExecutionException if the scheduler cannot accept a task
*/
- @Override
- void unpark() {
+ private void unpark(boolean lazySubmit) {
if (!getAndSetParkPermit(true) && currentThread() != this) {
int s = state();
// unparked while parked
if ((s == PARKED || s == TIMED_PARKED) && compareAndSetState(s, UNPARKED)) {
- submitRunContinuation();
+ if (lazySubmit) {
+ lazySubmitRunContinuation();
+ } else {
+ submitRunContinuation();
+ }
return;
}
@@ -870,6 +878,11 @@ void unpark() {
}
}
+ @Override
+ void unpark() {
+ unpark(false);
+ }
+
/**
* Invoked by unblocker thread to unblock this virtual thread.
*/
@@ -886,11 +899,7 @@ private void unblock() {
*/
private void parkTimeoutExpired() {
assert !VirtualThread.currentThread().isVirtual();
- if (!getAndSetParkPermit(true)
- && (state() == TIMED_PARKED)
- && compareAndSetState(TIMED_PARKED, UNPARKED)) {
- lazySubmitRunContinuation();
- }
+ unpark(true);
}
/**
diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java
index 9e50a1588e7..8f3d4ba29fd 100644
--- a/src/java.base/share/classes/java/security/KeyStore.java
+++ b/src/java.base/share/classes/java/security/KeyStore.java
@@ -37,6 +37,7 @@
import javax.security.auth.callback.*;
import sun.security.util.Debug;
+import sun.security.util.CryptoAlgorithmConstraints;
/**
* This class represents a storage facility for cryptographic
@@ -841,12 +842,21 @@ private String getProviderName() {
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
- * The JDK Reference Implementation additionally uses the
- * {@code jdk.security.provider.preferred}
+ * The JDK Reference Implementation additionally uses
+ *
+ *
the {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
- * the preferred provider order for the specified algorithm. This
+ * the preferred provider order for the specified keystore type. This
* may be different from the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
+ *
+ *
the {@code jdk.crypto.disabledAlgorithms}
+ * {@link Security#getProperty(String) Security} property to determine
+ * if the specified keystore type is allowed. If the
+ * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes
+ * the security property value.
+ *
{@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
+ *
{@link #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
* disabled.
- *
{@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
+ *
{@link #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
* disables caching. Values larger than this are not cached.
- *
{@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
+ *
{@link #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
*
*
* Here is a sample Maven invocation with caching disabled:
@@ -58,11 +58,11 @@
*
*
* @see Constant
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ConstantUtf8 extends Constant {
- private static class Cache {
+ private static final class Cache {
private static final boolean BCEL_STATISTICS = false;
private static final int MAX_ENTRIES = 20000;
@@ -82,7 +82,7 @@ protected boolean removeEldestEntry(final Map.Entry eldest
private static final int MAX_ENTRY_SIZE = 200;
static boolean isEnabled() {
- return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
+ return MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
}
}
@@ -117,6 +117,11 @@ static synchronized void clearStats() {
hits = considered = skipped = created = 0;
}
+ // Avoid Spotbugs complaint about Write to static field
+ private static void countCreated() {
+ created++;
+ }
+
/**
* Gets a new or cached instance of the given value.
*
@@ -203,7 +208,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) {
ConstantUtf8(final DataInput dataInput) throws IOException {
super(Const.CONSTANT_Utf8);
value = dataInput.readUTF();
- created++;
+ countCreated();
}
/**
@@ -212,7 +217,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) {
public ConstantUtf8(final String value) {
super(Const.CONSTANT_Utf8);
this.value = Objects.requireNonNull(value, "value");
- created++;
+ countCreated();
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
index 311e9a33fa3..143c2a25544 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
@@ -56,7 +56,7 @@ public ConstantValue(final ConstantValue c) {
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Name index in constant pool
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
index 90841d96081..c561afe33c5 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
@@ -59,7 +59,7 @@ public Deprecated(final int nameIndex, final int length, final byte[] bytes, fin
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
index 3c475891acd..934b608d6ac 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -22,12 +22,13 @@
import java.util.Objects;
import java.util.Stack;
import java.util.stream.Stream;
+import jdk.xml.internal.Utils;
/**
- * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
- * applied to all components of a JavaClass object. I.e. this class supplies the
- * traversal strategy, other classes can make use of it.
+ * Traverses a JavaClass with another Visitor object 'piggy-backed' that is applied to all components of a JavaClass
+ * object. I.e. this class supplies the traversal strategy, other classes can make use of it.
*
+ * @LastModified: Sept 2025
*/
public class DescendingVisitor implements Visitor {
private final JavaClass clazz;
@@ -46,7 +47,7 @@ public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
}
private void accept(final E[] node) {
- Stream.of(node).forEach(e -> e.accept(this));
+ Utils.streamOfIfNonNull(node).forEach(e -> e.accept(this));
}
/**
@@ -507,6 +508,21 @@ public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
stack.pop();
}
+ @Override
+ public void visitRecord(final Record record) {
+ stack.push(record);
+ record.accept(visitor);
+ accept(record.getComponents());
+ stack.pop();
+ }
+
+ @Override
+ public void visitRecordComponent(final RecordComponentInfo recordComponentInfo) {
+ stack.push(recordComponentInfo);
+ recordComponentInfo.accept(visitor);
+ stack.pop();
+ }
+
@Override
public void visitSignature(final Signature attribute) {
stack.push(attribute);
@@ -531,6 +547,20 @@ public void visitStackMap(final StackMap table) {
@Override
public void visitStackMapEntry(final StackMapEntry var) {
+ stack.push(var);
+ var.accept(visitor);
+ accept(var.getTypesOfLocals());
+ accept(var.getTypesOfStackItems());
+ stack.pop();
+ }
+
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param var object to visit
+ * @since 6.8.0
+ */
+ @Override
+ public void visitStackMapType(final StackMapType var) {
stack.push(var);
var.accept(visitor);
stack.pop();
@@ -549,4 +579,5 @@ public void visitUnknown(final Unknown attribute) {
attribute.accept(visitor);
stack.pop();
}
+
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
index 5c3d9b3172b..d87307c0e7d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -50,7 +50,7 @@
*}
*
* @since 6.0
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class ElementValue {
@@ -67,6 +67,7 @@ public abstract class ElementValue {
public static final byte PRIMITIVE_LONG = 'J';
public static final byte PRIMITIVE_SHORT = 'S';
public static final byte PRIMITIVE_BOOLEAN = 'Z';
+ static final ElementValue[] EMPTY_ARRAY = {};
/**
* Reads an {@code element_value} as an {@code ElementValue}.
@@ -124,7 +125,7 @@ public static ElementValue readElementValue(final DataInput input, final Constan
final int numArrayVals = input.readUnsignedShort();
final ElementValue[] evalues = new ElementValue[numArrayVals];
for (int j = 0; j < numArrayVals; j++) {
- evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting);
+ evalues[j] = readElementValue(input, cpool, arrayNesting);
}
return new ArrayElementValue(ARRAY, evalues, cpool);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
index 826ba41af70..db33c871656 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
@@ -315,6 +315,15 @@ public void visitStackMap(final StackMap obj) {
public void visitStackMapEntry(final StackMapEntry obj) {
}
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param obj object to visit
+ * @since 6.8.0
+ */
+ @Override
+ public void visitStackMapType(final StackMapType obj) {
+ }
+
@Override
public void visitSynthetic(final Synthetic obj) {
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
index 90eaa3eb062..1b6004b3740 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class represents the table of exceptions that are thrown by a method. This attribute may be used once per
@@ -43,7 +44,7 @@
* }
*
* @see Code
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ExceptionTable extends Attribute {
@@ -60,7 +61,7 @@ public ExceptionTable(final ExceptionTable c) {
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -85,7 +86,7 @@ public ExceptionTable(final ExceptionTable c) {
*/
public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) {
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
- this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
+ this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable);
Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length");
}
@@ -156,7 +157,7 @@ public int getNumberOfExceptions() {
* length.
*/
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
- this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
+ this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
index 7e6ccb2ecb5..8ffc796a0ea 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
@@ -42,45 +42,37 @@ public final class Field extends FieldOrMethod {
*/
public static final Field[] EMPTY_ARRAY = {};
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final Field THIS = (Field) o1;
- final Field THAT = (Field) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final Field a, final Field b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final Field THIS = (Field) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final Field o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * Empty array.
+ * @return Comparison strategy object.
*/
- static final Field[] EMPTY_FIELD_ARRAY = {};
-
- /**
- * @return Comparison strategy object
- */
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
- * @param file Input stream
+ * @param file Input stream.
*/
Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
super(file, constantPool);
@@ -133,7 +125,7 @@ public Field copy(final ConstantPool constantPool) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof Field && bcelComparator.equals(this, (Field) obj);
}
/**
@@ -149,14 +141,16 @@ public ConstantValue getConstantValue() {
}
/**
+ * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2
+ *
* @return type of field
*/
public Type getType() {
- return Type.getReturnType(getSignature());
+ return Type.getType(getSignature());
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
* signature.
*
* @see Object#hashCode()
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
index 1daa6a62fd5..679d5a9eb7c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,7 +28,7 @@
/**
* Abstract super class for fields and methods.
*
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
@@ -72,7 +72,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -88,7 +88,7 @@ protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) t
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -137,7 +137,7 @@ protected FieldOrMethod copy_(final ConstantPool constantPool) {
Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
return c;
} catch (final CloneNotSupportedException e) {
- throw new IllegalStateException(e);
+ throw new UnsupportedOperationException(e);
}
}
@@ -152,10 +152,8 @@ public final void dump(final DataOutputStream file) throws IOException {
file.writeShort(name_index);
file.writeShort(signature_index);
file.writeShort(attributes_count);
- if (attributes != null) {
- for (final Attribute attribute : attributes) {
- attribute.dump(file);
- }
+ for (final Attribute attribute : attributes) {
+ attribute.dump(file);
}
}
@@ -171,6 +169,22 @@ public AnnotationEntry[] getAnnotationEntries() {
return annotationEntries;
}
+ /**
+ * Gets attribute for given tag.
+ * @return Attribute for given tag, null if not found.
+ * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
+ * @since 6.10.0
+ */
+ @SuppressWarnings("unchecked")
+ public final T getAttribute(final byte tag) {
+ for (final Attribute attribute : getAttributes()) {
+ if (attribute.getTag() == tag) {
+ return (T) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @return Collection of object attributes.
*/
@@ -221,7 +235,7 @@ public final int getNameIndex() {
}
/**
- * @return String representation of object's type signature (java style)
+ * @return String representation of object's type signature (Java style)
*/
public final String getSignature() {
return constant_pool.getConstantUtf8(signature_index).getBytes();
@@ -238,8 +252,8 @@ public final int getSignatureIndex() {
* @param attributes Collection of object attributes.
*/
public final void setAttributes(final Attribute[] attributes) {
- this.attributes = attributes;
- this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
+ this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
+ this.attributes_count = this.attributes.length; // init deprecated field
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
index d77582815b7..82900dcca10 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
@@ -41,7 +41,7 @@ public final class InnerClass implements Cloneable, Node {
private int innerAccessFlags;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
index 2295ca5c625..b61be1effa0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
@@ -42,7 +42,7 @@ public final class InnerClasses extends Attribute implements Iterable iterator() {
* @param innerClasses the array of inner classes
*/
public void setInnerClasses(final InnerClass[] innerClasses) {
- this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
+ this.innerClasses = innerClasses != null ? innerClasses : EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java
new file mode 100644
index 00000000000..eaf1da2d2e1
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java
@@ -0,0 +1,53 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.bcel.internal.classfile;
+
+/**
+ * Thrown when the BCEL attempts to read a class file and determines that a class is malformed or otherwise cannot be interpreted as a class file.
+ *
+ * @since 6.8.0
+ */
+public class InvalidMethodSignatureException extends ClassFormatException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new instance with the specified invalid signature as the message.
+ *
+ * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method.
+ */
+ public InvalidMethodSignatureException(final String signature) {
+ super(signature);
+ }
+
+ /**
+ * Constructs a new instance with the specified invalid signature as the message and a cause.
+ *
+ * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method.
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that
+ * the cause is nonexistent or unknown.
+ */
+ public InvalidMethodSignatureException(final String signature, final Throwable cause) {
+ super(signature, cause);
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
index d6c4cfa6a07..1b0e2ed1ce0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -38,6 +38,7 @@
import com.sun.org.apache.bcel.internal.util.BCELComparator;
import com.sun.org.apache.bcel.internal.util.ClassQueue;
import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
+import jdk.xml.internal.Utils;
/**
* Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java
@@ -46,7 +47,7 @@
* classes should see the ClassGen class.
*
* @see com.sun.org.apache.bcel.internal.generic.ClassGen
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable {
@@ -67,26 +68,23 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
public static final byte HEAP = 1;
public static final byte FILE = 2;
public static final byte ZIP = 3;
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final JavaClass THIS = (JavaClass) o1;
- final JavaClass THAT = (JavaClass) o2;
- return Objects.equals(THIS.getClassName(), THAT.getClassName());
+ public boolean equals(final JavaClass a, final JavaClass b) {
+ return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName());
}
@Override
- public int hashCode(final Object o) {
- final JavaClass THIS = (JavaClass) o;
- return THIS.getClassName().hashCode();
+ public int hashCode(final JavaClass o) {
+ return o != null ? Objects.hashCode(o.getClassName()) : 0;
}
};
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
@@ -100,9 +98,9 @@ private static String indent(final Object obj) {
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -128,8 +126,10 @@ public static void setComparator(final BCELComparator comparator) {
private boolean isAnonymous;
private boolean isNested;
+ private boolean isRecord;
private boolean computedNestedTypeStatus;
+ private boolean computedRecord;
/**
* In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any
@@ -177,17 +177,15 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, final
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
final ConstantPool constantPool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes, final byte source) {
super(accessFlags);
- if (interfaces == null) {
- interfaces = Const.EMPTY_INT_ARRAY;
- }
+ interfaces = Utils.createEmptyArrayIfNull(interfaces);
if (attributes == null) {
attributes = Attribute.EMPTY_ARRAY;
}
if (fields == null) {
- fields = Field.EMPTY_FIELD_ARRAY;
+ fields = Field.EMPTY_ARRAY;
}
if (methods == null) {
- methods = Method.EMPTY_METHOD_ARRAY;
+ methods = Method.EMPTY_ARRAY;
}
this.classNameIndex = classNameIndex;
this.superclassNameIndex = superclassNameIndex;
@@ -254,6 +252,19 @@ public int compareTo(final JavaClass obj) {
return getClassName().compareTo(obj.getClassName());
}
+ private void computeIsRecord() {
+ if (computedRecord) {
+ return;
+ }
+ for (final Attribute attribute : this.attributes) {
+ if (attribute instanceof Record) {
+ isRecord = true;
+ break;
+ }
+ }
+ this.computedRecord = true;
+ }
+
private void computeNestedTypeStatus() {
if (computedNestedTypeStatus) {
return;
@@ -384,11 +395,51 @@ public void dump(final String fileName) throws IOException {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof JavaClass && bcelComparator.equals(this, (JavaClass) obj);
+ }
+
+ /**
+ * Finds a visible field by name and type in this class and its super classes.
+ * @param fieldName the field name to find
+ * @param fieldType the field type to find
+ * @return field matching given name and type, null if field is not found or not accessible from this class.
+ * @throws ClassNotFoundException
+ * @since 6.8.0
+ */
+ public Field findField(final String fieldName, final Type fieldType) throws ClassNotFoundException {
+ for (final Field field : fields) {
+ if (field.getName().equals(fieldName)) {
+ final Type fType = Type.getType(field.getSignature());
+ /*
+ * TODO: Check if assignment compatibility is sufficient. What does Sun do?
+ */
+ if (fType.equals(fieldType)) {
+ return field;
+ }
+ }
+ }
+
+ final JavaClass superclass = getSuperClass();
+ if (superclass != null && !"java.lang.Object".equals(superclass.getClassName())) {
+ final Field f = superclass.findField(fieldName, fieldType);
+ if (f != null && (f.isPublic() || f.isProtected() || !f.isPrivate() && packageName.equals(superclass.getPackageName()))) {
+ return f;
+ }
+ }
+ final JavaClass[] implementedInterfaces = getInterfaces();
+ if (implementedInterfaces != null) {
+ for (final JavaClass implementedInterface : implementedInterfaces) {
+ final Field f = implementedInterface.findField(fieldName, fieldType);
+ if (f != null) {
+ return f;
+ }
+ }
+ }
+ return null;
}
/**
- * Get all interfaces implemented by this JavaClass (transitively).
+ * Gets all interfaces implemented by this JavaClass (transitively).
*
* @throws ClassNotFoundException if any of the class's superclasses or interfaces can't be found.
*/
@@ -409,7 +460,7 @@ public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
queue.enqueue(iface);
}
}
- return allInterfaces.toArray(JavaClass.EMPTY_ARRAY);
+ return allInterfaces.toArray(EMPTY_ARRAY);
}
/**
@@ -424,6 +475,22 @@ public AnnotationEntry[] getAnnotationEntries() {
return annotations;
}
+ /**
+ * Gets attribute for given tag.
+ * @return Attribute for given tag, null if not found.
+ * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
+ * @since 6.10.0
+ */
+ @SuppressWarnings("unchecked")
+ public final T getAttribute(final byte tag) {
+ for (final Attribute attribute : getAttributes()) {
+ if (attribute.getTag() == tag) {
+ return (T) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @return Attributes of the class.
*/
@@ -495,7 +562,7 @@ public String[] getInterfaceNames() {
}
/**
- * Get interfaces directly implemented by this JavaClass.
+ * Gets interfaces directly implemented by this JavaClass.
*
* @throws ClassNotFoundException if any of the class's interfaces can't be found.
*/
@@ -587,7 +654,7 @@ public String getSourceFilePath() {
}
/**
- * @return the superclass for this JavaClass object, or null if this is java.lang.Object
+ * @return the superclass for this JavaClass object, or null if this is {@link Object}
* @throws ClassNotFoundException if the superclass can't be found
*/
public JavaClass getSuperClass() throws ClassNotFoundException {
@@ -607,12 +674,12 @@ public JavaClass[] getSuperClasses() throws ClassNotFoundException {
for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
allSuperClasses.add(clazz);
}
- return allSuperClasses.toArray(JavaClass.EMPTY_ARRAY);
+ return allSuperClasses.toArray(EMPTY_ARRAY);
}
/**
- * returns the super class name of this class. In the case that this class is java.lang.Object, it will return itself
- * (java.lang.Object). This is probably incorrect but isn't fixed at this time to not break existing clients.
+ * returns the super class name of this class. In the case that this class is {@link Object}, it will return itself
+ * ({@link Object}). This is probably incorrect but isn't fixed at this time to not break existing clients.
*
* @return Superclass name.
*/
@@ -628,7 +695,7 @@ public int getSuperclassNameIndex() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name.
*
* @see Object#hashCode()
*/
@@ -645,7 +712,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep
if (!inter.isInterface()) {
throw new IllegalArgumentException(inter.getClassName() + " is no interface");
}
- if (this.equals(inter)) {
+ if (equals(inter)) {
return true;
}
final JavaClass[] superInterfaces = getAllInterfaces();
@@ -664,7 +731,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep
* @throws ClassNotFoundException if superclasses or superinterfaces of this object can't be found
*/
public final boolean instanceOf(final JavaClass superclass) throws ClassNotFoundException {
- if (this.equals(superclass)) {
+ if (equals(superclass)) {
return true;
}
for (final JavaClass clazz : getSuperClasses()) {
@@ -698,6 +765,17 @@ public final boolean isNested() {
return this.isNested;
}
+ /**
+ * Tests whether this class was declared as a record
+ *
+ * @return true if a record attribute is present, false otherwise.
+ * @since 6.9.0
+ */
+ public boolean isRecord() {
+ computeIsRecord();
+ return this.isRecord;
+ }
+
public final boolean isSuper() {
return (super.getAccessFlags() & Const.ACC_SUPER) != 0;
}
@@ -706,7 +784,7 @@ public final boolean isSuper() {
* @param attributes .
*/
public void setAttributes(final Attribute[] attributes) {
- this.attributes = attributes;
+ this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
}
/**
@@ -734,11 +812,11 @@ public void setConstantPool(final ConstantPool constantPool) {
* @param fields .
*/
public void setFields(final Field[] fields) {
- this.fields = fields;
+ this.fields = fields != null ? fields : Field.EMPTY_ARRAY;
}
/**
- * Set File name of class, aka SourceFile attribute value
+ * Sets File name of class, aka SourceFile attribute value
*/
public void setFileName(final String fileName) {
this.fileName = fileName;
@@ -748,14 +826,14 @@ public void setFileName(final String fileName) {
* @param interfaceNames .
*/
public void setInterfaceNames(final String[] interfaceNames) {
- this.interfaceNames = interfaceNames;
+ this.interfaceNames = Utils.createEmptyArrayIfNull(interfaceNames, String[].class);
}
/**
* @param interfaces .
*/
public void setInterfaces(final int[] interfaces) {
- this.interfaces = interfaces;
+ this.interfaces = Utils.createEmptyArrayIfNull(interfaces);
}
/**
@@ -769,7 +847,7 @@ public void setMajor(final int major) {
* @param methods .
*/
public void setMethods(final Method[] methods) {
- this.methods = methods;
+ this.methods = methods != null ? methods : Method.EMPTY_ARRAY;
}
/**
@@ -787,7 +865,7 @@ public void setRepository(final com.sun.org.apache.bcel.internal.util.Repository
}
/**
- * Set absolute path to file this class was read from.
+ * Sets absolute path to file this class was read from.
*/
public void setSourceFileName(final String sourceFileName) {
this.sourceFileName = sourceFileName;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
index 4380d04bc06..dc41ad065f8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
@@ -40,11 +40,11 @@ public final class LineNumber implements Cloneable, Node {
/** Program Counter (PC) corresponds to line */
private int startPc;
- /** number in source file */
+ /** Number in source file */
private int lineNumber;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
index 6251fc514cc..96541f309bd 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -36,7 +36,7 @@
*
* @see Code
* @see LineNumber
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public final class LineNumberTable extends Attribute implements Iterable {
@@ -44,7 +44,7 @@ public final class LineNumberTable extends Attribute implements Iterable
+ * Note that both objects use the same references (shallow copy). Use copy() for a physical copy.
+ *
*/
public LineNumberTable(final LineNumberTable c) {
this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool());
@@ -190,7 +191,7 @@ public Iterator iterator() {
* @param lineNumberTable the line number entries for this table
*/
public void setLineNumberTable(final LineNumber[] lineNumberTable) {
- this.lineNumberTable = lineNumberTable;
+ this.lineNumberTable = lineNumberTable != null ? lineNumberTable : LineNumber.EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
index fd56e14a539..26fde9bdbdf 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
@@ -40,10 +40,12 @@
*/
public class LocalVariableTable extends Attribute implements Iterable {
+ private static final LocalVariable[] EMPTY_ARRAY = {};
+
private LocalVariable[] localVariableTable; // variables
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -68,7 +70,7 @@ public class LocalVariableTable extends Attribute implements Iterable iterator() {
}
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
- this.localVariableTable = localVariableTable;
+ this.localVariableTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
index 08868a82de8..ce327e20f52 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
@@ -63,14 +63,14 @@
*/
public class LocalVariableTypeTable extends Attribute implements Iterable {
+ private static final LocalVariable[] EMPTY_ARRAY = {};
+
private LocalVariable[] localVariableTypeTable; // variables
LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
this(nameIdx, len, (LocalVariable[]) null, cpool);
-
final int localVariableTypeTableLength = input.readUnsignedShort();
localVariableTypeTable = new LocalVariable[localVariableTypeTableLength];
-
for (int i = 0; i < localVariableTypeTableLength; i++) {
localVariableTypeTable[i] = new LocalVariable(input, cpool);
}
@@ -97,7 +97,6 @@ public void accept(final Visitor v) {
@Override
public Attribute copy(final ConstantPool constantPool) {
final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
-
c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy());
c.setConstantPool(constantPool);
@@ -119,7 +118,6 @@ public final LocalVariable getLocalVariable(final int index) {
return variable;
}
}
-
return null;
}
@@ -137,7 +135,7 @@ public Iterator iterator() {
}
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
- this.localVariableTypeTable = localVariableTable;
+ this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
}
/**
@@ -146,15 +144,12 @@ public final void setLocalVariableTable(final LocalVariable[] localVariableTable
@Override
public final String toString() {
final StringBuilder buf = new StringBuilder();
-
for (int i = 0; i < localVariableTypeTable.length; i++) {
buf.append(localVariableTypeTable[i].toStringShared(true));
-
if (i < localVariableTypeTable.length - 1) {
buf.append('\n');
}
}
-
return buf.toString();
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
index ba2623eec08..643c820f366 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
@@ -40,42 +40,34 @@ public final class Method extends FieldOrMethod {
*/
public static final Method[] EMPTY_ARRAY = {};
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final Method THIS = (Method) o1;
- final Method THAT = (Method) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final Method a, final Method b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final Method THIS = (Method) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final Method o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * Empty array.
+ * @return Comparison strategy object.
*/
- static final Method[] EMPTY_METHOD_ARRAY = {};
-
- /**
- * @return Comparison strategy object
- */
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
- // annotations defined on the parameters of a method
+ /** Annotations defined on the parameters of a method. */
private ParameterAnnotationEntry[] parameterAnnotationEntries;
/**
@@ -85,7 +77,7 @@ public Method() {
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -142,7 +134,7 @@ public Method copy(final ConstantPool constantPool) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof Method && bcelComparator.equals(this, (Method) obj);
}
/**
@@ -189,7 +181,7 @@ public LineNumberTable getLineNumberTable() {
}
/**
- * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute.
+ * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code attribute.
*/
public LocalVariableTable getLocalVariableTable() {
final Code code = getCode();
@@ -199,6 +191,19 @@ public LocalVariableTable getLocalVariableTable() {
return code.getLocalVariableTable();
}
+ /**
+ * Gets the local variable type table attribute {@link LocalVariableTypeTable}.
+ * @return LocalVariableTypeTable of code attribute if any, i.e. the call is forwarded to the Code attribute.
+ * @since 6.10.0
+ */
+ public LocalVariableTypeTable getLocalVariableTypeTable() {
+ final Code code = getCode();
+ if (code == null) {
+ return null;
+ }
+ return code.getLocalVariableTypeTable();
+ }
+
/**
* @return Annotations on the parameters of a method
* @since 6.0
@@ -218,7 +223,7 @@ public Type getReturnType() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR
* signature.
*
* @see Object#hashCode()
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
index ffc1a20f80a..865e154d334 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
@@ -29,6 +29,9 @@
/**
* Entry of the parameters table.
+ *
+ * Implements {@link Node} as of 6.7.0.
+ *
*
* @see The class File Format :
* The MethodParameters Attribute
@@ -46,7 +49,7 @@ public MethodParameter() {
}
/**
- * Construct object from input stream.
+ * Constructs an instance from a DataInput.
*
* @param input Input stream
* @throws IOException if an I/O error occurs.
@@ -75,7 +78,7 @@ public MethodParameter copy() {
}
/**
- * Dump object to file stream on binary format.
+ * Dumps object to file stream on binary format.
*
* @param file Output file stream
* @throws IOException if an I/O error occurs.
@@ -94,7 +97,10 @@ public int getNameIndex() {
}
/**
- * Returns the name of the parameter.
+ * Gets the name of the parameter.
+ *
+ * @param constantPool The pool to query.
+ * @return Constant from the given pool.
*/
public String getParameterName(final ConstantPool constantPool) {
if (nameIndex == 0) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
index 5b5d1d77f6f..2f5bffd8d3c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
@@ -42,13 +42,12 @@ public class MethodParameters extends Attribute implements Iterable parameters[i].copy());
c.setConstantPool(constantPool);
return c;
@@ -96,6 +94,6 @@ public Iterator iterator() {
}
public void setParameters(final MethodParameter[] parameters) {
- this.parameters = parameters;
+ this.parameters = parameters != null ? parameters : EMPTY_ARRAY;
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
index 00eebe18245..addf6f0aea3 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
@@ -44,19 +44,27 @@ public final class Module extends Attribute {
*/
public static final String EXTENSION = ".jmod";
+ private static String getClassNameAtIndex(final ConstantPool cp, final int index, final boolean compactClassName) {
+ final String className = cp.getConstantString(index, Const.CONSTANT_Class);
+ if (compactClassName) {
+ return Utility.compactClassName(className, false);
+ }
+ return className;
+ }
private final int moduleNameIndex;
private final int moduleFlags;
- private final int moduleVersionIndex;
+ private final int moduleVersionIndex;
private ModuleRequires[] requiresTable;
private ModuleExports[] exportsTable;
private ModuleOpens[] opensTable;
private final int usesCount;
private final int[] usesIndex;
+
private ModuleProvides[] providesTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -113,8 +121,6 @@ public void accept(final Visitor v) {
v.visitModule(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this attribute
*/
@@ -186,6 +192,25 @@ public ModuleExports[] getExportsTable() {
return exportsTable;
}
+ /**
+ * Gets flags for this module.
+ * @return module flags
+ * @since 6.10.0
+ */
+ public int getModuleFlags() {
+ return moduleFlags;
+ }
+
+ /**
+ * Gets module name.
+ * @param cp Array of constants
+ * @return module name
+ * @since 6.10.0
+ */
+ public String getModuleName(final ConstantPool cp) {
+ return cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module);
+ }
+
/**
* @return table of provided interfaces
* @see ModuleOpens
@@ -210,6 +235,31 @@ public ModuleRequires[] getRequiresTable() {
return requiresTable;
}
+ /**
+ * Gets the array of class names for this module's uses.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @param compactClassName false for original constant pool value, true to replace '/' with '.'
+ * @return array of used class names
+ * @since 6.10.0
+ */
+ public String[] getUsedClassNames(final ConstantPool constantPool, final boolean compactClassName) {
+ final String[] usedClassNames = new String[usesCount];
+ for (int i = 0; i < usesCount; i++) {
+ usedClassNames[i] = getClassNameAtIndex(constantPool, usesIndex[i], compactClassName);
+ }
+ return usedClassNames;
+ }
+
+ /**
+ * Gets version for this module.
+ * @param cp Array of constants
+ * @return version from constant pool, "0" if version index is 0
+ * @since 6.10.0
+ */
+ public String getVersion(final ConstantPool cp) {
+ return moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
+ }
+
/**
* @return String representation, i.e., a list of packages.
*/
@@ -218,9 +268,9 @@ public String toString() {
final ConstantPool cp = super.getConstantPool();
final StringBuilder buf = new StringBuilder();
buf.append("Module:\n");
- buf.append(" name: ").append(Utility.pathToPackage(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module))).append("\n");
+ buf.append(" name: ").append(Utility.pathToPackage(getModuleName(cp))).append("\n");
buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n");
- final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
+ final String version = getVersion(cp);
buf.append(" version: ").append(version).append("\n");
buf.append(" requires(").append(requiresTable.length).append("):\n");
@@ -240,8 +290,8 @@ public String toString() {
buf.append(" uses(").append(usesIndex.length).append("):\n");
for (final int index : usesIndex) {
- final String className = cp.getConstantString(index, Const.CONSTANT_Class);
- buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
+ final String className = getClassNameAtIndex(cp, index, true);
+ buf.append(" ").append(className).append("\n");
}
buf.append(" provides(").append(providesTable.length).append("):\n");
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
index 8a97f4b6d08..f92f508b862 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
@@ -36,13 +36,17 @@
*/
public final class ModuleExports implements Cloneable, Node {
+ private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) {
+ return constantPool.getConstantString(index, Const.CONSTANT_Module);
+ }
private final int exportsIndex; // points to CONSTANT_Package_info
private final int exportsFlags;
private final int exportsToCount;
+
private final int[] exportsToIndex; // points to CONSTANT_Module_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -68,8 +72,6 @@ public void accept(final Visitor v) {
v.visitModuleExports(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the flags for this ModuleExports.
+ * @return the exportsFlags
+ * @since 6.10.0
+ */
+ public int getExportsFlags() {
+ return exportsFlags;
+ }
+
+ /**
+ * Gets the exported package name.
+ * @param constantPool the constant pool from the ClassFile
+ * @return the exported package name
+ * @since 6.10.0
+ */
+ public String getPackageName(final ConstantPool constantPool) {
+ return constantPool.constantToString(exportsIndex, Const.CONSTANT_Package);
+ }
+
+ /**
+ * Gets an array of module names for this ModuleExports.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return array of module names following 'exports to'
+ * @since 6.10.0
+ */
+ public String[] getToModuleNames(final ConstantPool constantPool) {
+ final String[] toModuleNames = new String[exportsToCount];
+ for (int i = 0; i < exportsToCount; i++) {
+ toModuleNames[i] = getToModuleNameAtIndex(constantPool, exportsToIndex[i]);
+ }
+ return toModuleNames;
+ }
+
/**
* @return String representation
*/
@@ -110,13 +145,13 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String packageName = constantPool.constantToString(exportsIndex, Const.CONSTANT_Package);
- buf.append(Utility.compactClassName(packageName, false));
+ final String packageName = getPackageName(constantPool);
+ buf.append(packageName);
buf.append(", ").append(String.format("%04x", exportsFlags));
buf.append(", to(").append(exportsToCount).append("):\n");
for (final int index : exportsToIndex) {
- final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
- buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
+ final String moduleName = getToModuleNameAtIndex(constantPool, index);
+ buf.append(" ").append(moduleName).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
index a6ffd882862..b73bd01f794 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
@@ -39,7 +39,7 @@ public final class ModuleMainClass extends Attribute {
private int mainClassIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
index 06b404df72b..388370a45e7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
@@ -36,13 +36,17 @@
*/
public final class ModuleOpens implements Cloneable, Node {
+ private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) {
+ return constantPool.getConstantString(index, Const.CONSTANT_Module);
+ }
private final int opensIndex; // points to CONSTANT_Package_info
private final int opensFlags;
private final int opensToCount;
+
private final int[] opensToIndex; // points to CONSTANT_Module_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -68,8 +72,6 @@ public void accept(final Visitor v) {
v.visitModuleOpens(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the flags for this ModuleOpens.
+ * @return the opensFlags
+ * @since 6.10.0
+ */
+ public int getOpensFlags() {
+ return opensFlags;
+ }
+
+ /**
+ * Gets the opened package name.
+ * @param constantPool the constant pool from the ClassFile
+ * @return the opened package name
+ * @since 6.10.0
+ */
+ public String getPackageName(final ConstantPool constantPool) {
+ return constantPool.constantToString(opensIndex, Const.CONSTANT_Package);
+ }
+
+ /**
+ * Gets an array of module names for this ModuleOpens.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return array of module names following 'opens to'
+ * @since 6.10.0
+ */
+ public String[] getToModuleNames(final ConstantPool constantPool) {
+ final String[] toModuleNames = new String[opensToCount];
+ for (int i = 0; i < opensToCount; i++) {
+ toModuleNames[i] = getToModuleNameAtIndex(constantPool, opensToIndex[i]);
+ }
+ return toModuleNames;
+ }
+
/**
* @return String representation
*/
@@ -110,13 +145,13 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String packageName = constantPool.constantToString(opensIndex, Const.CONSTANT_Package);
- buf.append(Utility.compactClassName(packageName, false));
+ final String packageName = getPackageName(constantPool);
+ buf.append(packageName);
buf.append(", ").append(String.format("%04x", opensFlags));
buf.append(", to(").append(opensToCount).append("):\n");
for (final int index : opensToIndex) {
- final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
- buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
+ final String moduleName = getToModuleNameAtIndex(constantPool, index);
+ buf.append(" ").append(moduleName).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
index 96367e02d2d..f48587e5455 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,20 +27,21 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class is derived from Attribute and represents the list of packages that are exported or opened by the
* Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure.
*
* @see Attribute
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ModulePackages extends Attribute {
private int[] packageIndexTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -65,7 +66,7 @@ public final class ModulePackages extends Attribute {
*/
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) {
super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool);
- this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
+ this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable);
Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length");
}
@@ -145,7 +146,7 @@ public String[] getPackageNames() {
* @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length.
*/
public void setPackageIndexTable(final int[] packageIndexTable) {
- this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
+ this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
index f6c6058dfbb..490e9cd5d44 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
@@ -36,12 +36,20 @@
*/
public final class ModuleProvides implements Cloneable, Node {
+ private static String getImplementationClassNameAtIndex(final ConstantPool constantPool, final int index, final boolean compactClassName) {
+ final String className = constantPool.getConstantString(index, Const.CONSTANT_Class);
+ if (compactClassName) {
+ return Utility.compactClassName(className, false);
+ }
+ return className;
+ }
private final int providesIndex; // points to CONSTANT_Class_info
private final int providesWithCount;
+
private final int[] providesWithIndex; // points to CONSTANT_Class_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -66,8 +74,6 @@ public void accept(final Visitor v) {
v.visitModuleProvides(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -94,6 +100,31 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the array of implementation class names for this ModuleProvides.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @param compactClassName false for original constant pool value, true to replace '/' with '.'
+ * @return array of implementation class names
+ * @since 6.10.0
+ */
+ public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) {
+ final String[] implementationClassNames = new String[providesWithCount];
+ for (int i = 0; i < providesWithCount; i++) {
+ implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName);
+ }
+ return implementationClassNames;
+ }
+
+ /**
+ * Gets the interface name for this ModuleProvides.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return interface name
+ * @since 6.10.0
+ */
+ public String getInterfaceName(final ConstantPool constantPool) {
+ return constantPool.constantToString(providesIndex, Const.CONSTANT_Class);
+ }
+
/**
* @return String representation
*/
@@ -107,12 +138,12 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class);
- buf.append(Utility.compactClassName(interfaceName, false));
+ final String interfaceName = getInterfaceName(constantPool);
+ buf.append(interfaceName);
buf.append(", with(").append(providesWithCount).append("):\n");
for (final int index : providesWithIndex) {
- final String className = constantPool.getConstantString(index, Const.CONSTANT_Class);
- buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
+ final String className = getImplementationClassNameAtIndex(constantPool, index, true);
+ buf.append(" ").append(className).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
index c9c26c20649..3149a18290b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
@@ -41,7 +41,7 @@ public final class ModuleRequires implements Cloneable, Node {
private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -63,8 +63,6 @@ public void accept(final Visitor v) {
v.visitModuleRequires(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -89,6 +87,35 @@ public void dump(final DataOutputStream file) throws IOException {
file.writeShort(requiresVersionIndex);
}
+ /**
+ * Gets the module name from the constant pool.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return module name
+ * @since 6.10.0
+ */
+ public String getModuleName(final ConstantPool constantPool) {
+ return constantPool.constantToString(requiresIndex, Const.CONSTANT_Module);
+ }
+
+ /**
+ * Gets the flags for this ModuleRequires.
+ * @return the requiresFlags
+ * @since 6.10.0
+ */
+ public int getRequiresFlags() {
+ return requiresFlags;
+ }
+
+ /**
+ * Gets the required version from the constant pool.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return required version, "0" if version index is 0.
+ * @since 6.10.0
+ */
+ public String getVersion(final ConstantPool constantPool) {
+ return requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
+ }
+
/**
* @return String representation
*/
@@ -102,10 +129,10 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module);
- buf.append(Utility.compactClassName(moduleName, false));
+ final String moduleName = getModuleName(constantPool);
+ buf.append(moduleName);
buf.append(", ").append(String.format("%04x", requiresFlags));
- final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
+ final String version = getVersion(constantPool);
buf.append(", ").append(version);
return buf.toString();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
index 05d982ca6e8..261f57d98a8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class is derived from Attribute and records the classes and interfaces that are authorized to claim
@@ -34,14 +35,14 @@
* ClassFile structure.
*
* @see Attribute
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class NestMembers extends Attribute {
private int[] classes;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -66,7 +67,7 @@ public final class NestMembers extends Attribute {
*/
public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) {
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
- this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
+ this.classes = Utils.createEmptyArrayIfNull(classes);
Args.requireU2(this.classes.length, "classes.length");
}
@@ -146,7 +147,7 @@ public int getNumberClasses() {
* @param classes the list of class indexes Also redefines number_of_classes according to table length.
*/
public void setClasses(final int[] classes) {
- this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
+ this.classes = Utils.createEmptyArrayIfNull(classes);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
index c0395732d79..792ef31cb72 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
@@ -26,5 +26,5 @@
*/
public interface Node {
- void accept(Visitor obj);
+ void accept(Visitor visitor);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
index 9b1dd4c7b41..b7b5e1f1d99 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
@@ -38,7 +38,7 @@ public final class PMGClass extends Attribute {
private int pmgIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
index a3070fa7e0c..6ebe60c8049 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
@@ -37,22 +37,28 @@ public class ParameterAnnotationEntry implements Node {
static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
- public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
+ public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attributes) {
+ if (attributes == null) {
+ return EMPTY_ARRAY;
+ }
// Find attributes that contain parameter annotation data
- final List accumulatedAnnotations = new ArrayList<>(attrs.length);
- for (final Attribute attribute : attrs) {
+ final List accumulatedAnnotations = new ArrayList<>(attributes.length);
+ for (final Attribute attribute : attributes) {
if (attribute instanceof ParameterAnnotations) {
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute;
- Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
+ final ParameterAnnotationEntry[] parameterAnnotationEntries = runtimeAnnotations.getParameterAnnotationEntries();
+ if (parameterAnnotationEntries != null) {
+ Collections.addAll(accumulatedAnnotations, parameterAnnotationEntries);
+ }
}
}
- return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY);
+ return accumulatedAnnotations.toArray(EMPTY_ARRAY);
}
private final AnnotationEntry[] annotationTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param input Input stream
* @throws IOException if an I/O error occurs.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
index 4817793120f..1e056b5d4f8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
@@ -34,10 +34,14 @@
*/
public abstract class ParameterAnnotations extends Attribute implements Iterable {
+ private static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
+
/** Table of parameter annotations */
private ParameterAnnotationEntry[] parameterAnnotationTable;
/**
+ * Constructs a new instance.
+ *
* @param parameterAnnotationType the subclass type of the parameter annotation
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
@@ -55,6 +59,8 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable
}
/**
+ * Constructs a new instance.
+ *
* @param parameterAnnotationType the subclass type of the parameter annotation
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
@@ -120,6 +126,6 @@ public Iterator iterator() {
* @param parameterAnnotationTable the entries to set in this parameter annotation
*/
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) {
- this.parameterAnnotationTable = parameterAnnotationTable;
+ this.parameterAnnotationTable = parameterAnnotationTable != null ? parameterAnnotationTable : EMPTY_ARRAY;
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java
new file mode 100644
index 00000000000..f59cfa37ca4
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java
@@ -0,0 +1,153 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.bcel.internal.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.sun.org.apache.bcel.internal.Const;
+import com.sun.org.apache.bcel.internal.util.Args;
+
+/**
+ * Extends {@link Attribute} and records the classes and
+ * interfaces that are authorized to claim membership in the nest hosted by the
+ * current class or interface. There may be at most one Record attribute in a
+ * ClassFile structure.
+ *
+ * @see Attribute
+ * @since 6.9.0
+ */
+public final class Record extends Attribute {
+
+ private static final RecordComponentInfo[] EMPTY_RCI_ARRAY = {};
+
+ private static RecordComponentInfo[] readComponents(final DataInput input, final ConstantPool constantPool)
+ throws IOException {
+ final int classCount = input.readUnsignedShort();
+ final RecordComponentInfo[] components = new RecordComponentInfo[classCount];
+ for (int i = 0; i < classCount; i++) {
+ components[i] = new RecordComponentInfo(input, constantPool);
+ }
+ return components;
+ }
+
+ private RecordComponentInfo[] components;
+
+ /**
+ * Constructs object from input stream.
+ *
+ * @param nameIndex Index in constant pool
+ * @param length Content length in bytes
+ * @param input Input stream
+ * @param constantPool Array of constants
+ * @throws IOException if an I/O error occurs.
+ */
+ Record(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
+ throws IOException {
+ this(nameIndex, length, readComponents(input, constantPool), constantPool);
+ }
+
+ /**
+ * Constructs a new instance using components.
+ *
+ * @param nameIndex Index in constant pool
+ * @param length Content length in bytes
+ * @param classes Array of Record Component Info elements
+ * @param constantPool Array of constants
+ */
+ public Record(final int nameIndex, final int length, final RecordComponentInfo[] classes,
+ final ConstantPool constantPool) {
+ super(Const.ATTR_RECORD, nameIndex, length, constantPool);
+ this.components = classes != null ? classes : EMPTY_RCI_ARRAY;
+ Args.requireU2(this.components.length, "attributes.length");
+ }
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitly
+ * defined by the contents of a Java class. For example, the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ @Override
+ public void accept(final Visitor v) {
+ v.visitRecord(this);
+ }
+
+ /**
+ * Copies this instance and its components.
+ *
+ * @return a deep copy of this instance and its components.
+ */
+ @Override
+ public Attribute copy(final ConstantPool constantPool) {
+ final Record c = (Record) clone();
+ if (components.length > 0) {
+ c.components = components.clone();
+ }
+ c.setConstantPool(constantPool);
+ return c;
+ }
+
+ /**
+ * Dumps this instance into a file stream in binary format.
+ *
+ * @param file output stream.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public void dump(final DataOutputStream file) throws IOException {
+ super.dump(file);
+ file.writeShort(components.length);
+ for (final RecordComponentInfo component : components) {
+ component.dump(file);
+ }
+ }
+
+ /**
+ * Gets all the record components.
+ *
+ * @return array of Record Component Info elements.
+ */
+ public RecordComponentInfo[] getComponents() {
+ return components;
+ }
+
+ /**
+ * Converts this instance to a String suitable for debugging.
+ *
+ * @return String a String suitable for debugging.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("Record(");
+ buf.append(components.length);
+ buf.append("):\n");
+ for (final RecordComponentInfo component : components) {
+ buf.append(" ").append(component.toString()).append("\n");
+ }
+ return buf.substring(0, buf.length() - 1); // remove the last newline
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java
new file mode 100644
index 00000000000..3679647d409
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java
@@ -0,0 +1,139 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.sun.org.apache.bcel.internal.Const;
+
+/**
+ * Record component info from a record. Instances from this class maps
+ * every component from a given record.
+ *
+ * @see
+ * The Java Virtual Machine Specification, Java SE 14 Edition, Records (preview)
+ * @since 6.9.0
+ */
+public class RecordComponentInfo implements Node {
+
+ private final int index;
+ private final int descriptorIndex;
+ private final Attribute[] attributes;
+ private final ConstantPool constantPool;
+
+ /**
+ * Constructs a new instance from an input stream.
+ *
+ * @param input Input stream
+ * @param constantPool Array of constants
+ * @throws IOException if an I/O error occurs.
+ */
+ public RecordComponentInfo(final DataInput input, final ConstantPool constantPool) throws IOException {
+ this.index = input.readUnsignedShort();
+ this.descriptorIndex = input.readUnsignedShort();
+ final int attributesCount = input.readUnsignedShort();
+ this.attributes = new Attribute[attributesCount];
+ for (int j = 0; j < attributesCount; j++) {
+ attributes[j] = Attribute.readAttribute(input, constantPool);
+ }
+ this.constantPool = constantPool;
+ }
+
+ @Override
+ public void accept(final Visitor v) {
+ v.visitRecordComponent(this);
+ }
+
+ /**
+ * Dumps contents into a file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException if an I/O error occurs.
+ */
+ public void dump(final DataOutputStream file) throws IOException {
+ file.writeShort(index);
+ file.writeShort(descriptorIndex);
+ file.writeShort(attributes.length);
+ for (final Attribute attribute : attributes) {
+ attribute.dump(file);
+ }
+ }
+
+ /**
+ * Gets all attributes.
+ *
+ * @return all attributes.
+ */
+ public Attribute[] getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Gets the constant pool.
+ *
+ * @return Constant pool.
+ */
+ public ConstantPool getConstantPool() {
+ return constantPool;
+ }
+
+ /**
+ * Gets the description index.
+ *
+ * @return index in constant pool of this record component descriptor.
+ */
+ public int getDescriptorIndex() {
+ return descriptorIndex;
+ }
+
+ /**
+ * Gets the name index.
+ *
+ * @return index in constant pool of this record component name.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Converts this instance to a String suitable for debugging.
+ *
+ * @return a String suitable for debugging.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("RecordComponentInfo(");
+ buf.append(constantPool.getConstantString(index, Const.CONSTANT_Utf8));
+ buf.append(",");
+ buf.append(constantPool.getConstantString(descriptorIndex, Const.CONSTANT_Utf8));
+ buf.append(",");
+ buf.append(attributes.length);
+ buf.append("):\n");
+ for (final Attribute attribute : attributes) {
+ buf.append(" ").append(attribute.toString()).append("\n");
+ }
+ return buf.substring(0, buf.length() - 1); // remove the last newline
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
index 7afb8719559..7a7c539f15a 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
@@ -28,13 +28,15 @@
import com.sun.org.apache.bcel.internal.Const;
/**
- * represents an annotation that is represented in the class file but is not provided to the JVM.
+ * An annotation that is represented in the class file but is not provided to the JVM.
*
* @since 6.0
*/
public class RuntimeInvisibleAnnotations extends Annotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
@@ -46,7 +48,9 @@ public RuntimeInvisibleAnnotations(final int nameIndex, final int length, final
}
/**
- * @return deep copy of this attribute
+ * Creates a deep copy of this attribute.
+ *
+ * @return deep copy of this attribute.
*/
@Override
public Attribute copy(final ConstantPool constantPool) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
index e4c3276f968..3d50ce16d40 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
@@ -34,6 +34,8 @@
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
index c91c77387b9..4bf8e6f7197 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
@@ -28,13 +28,15 @@
import com.sun.org.apache.bcel.internal.Const;
/**
- * represents an annotation that is represented in the class file and is provided to the JVM.
+ * An annotation that is represented in the class file and is provided to the JVM.
*
* @since 6.0
*/
public class RuntimeVisibleAnnotations extends Annotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
@@ -46,7 +48,9 @@ public RuntimeVisibleAnnotations(final int nameIndex, final int length, final Da
}
/**
- * @return deep copy of this attribute
+ * Creates a deep copy of this attribute.
+ *
+ * @return deep copy of this attribute.
*/
@Override
public Attribute copy(final ConstantPool constantPool) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
index 7e5d7eaaca3..ab5355235f6 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
@@ -34,6 +34,8 @@
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
index 4f5d3a341b3..2161bbcb6ec 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
@@ -110,7 +110,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
if ((ch = in.read()) == -1) {
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF");
}
- // System.out.println("return from ident:" + (char)ch);
+ // System.out.println("return from ident:" + (char) ch);
if (!identStart(ch)) {
final StringBuilder buf2 = new StringBuilder();
int count = 1;
@@ -128,7 +128,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
buf.append(buf2);
ch = in.read();
in.unread();
- // System.out.println("so far:" + buf2 + ":next:" +(char)ch);
+ // System.out.println("so far:" + buf2 + ":next:" +(char) ch);
} else {
for (int i = 0; i < count; i++) {
in.unread();
@@ -141,10 +141,10 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
do {
buf2.append((char) ch);
ch = in.read();
- // System.out.println("within ident:"+ (char)ch);
+ // System.out.println("within ident:"+ (char) ch);
} while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/'));
buf.append(Utility.pathToPackage(buf2.toString()));
- // System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
+ // System.out.println("regular return ident:"+ (char) ch + ":" + buf2);
if (ch != -1) {
in.unread();
}
@@ -160,7 +160,7 @@ public static String translate(final String s) {
private int signatureIndex;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
index 5e4e98d94df..e3e1cf40031 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
@@ -54,7 +54,7 @@ public void dump(final DataOutputStream dos) throws IOException {
dos.writeShort(getIndex());
break;
default:
- throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type);
+ throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type);
}
}
@@ -67,7 +67,7 @@ public int getIndex() {
public boolean getValueBoolean() {
if (super.getType() != PRIMITIVE_BOOLEAN) {
- throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue");
+ throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue");
}
final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
return bo.getBytes() != 0;
@@ -75,21 +75,21 @@ public boolean getValueBoolean() {
public byte getValueByte() {
if (super.getType() != PRIMITIVE_BYTE) {
- throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue");
+ throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue");
}
return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public char getValueChar() {
if (super.getType() != PRIMITIVE_CHAR) {
- throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue");
+ throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue");
}
return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public double getValueDouble() {
if (super.getType() != PRIMITIVE_DOUBLE) {
- throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue");
+ throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue");
}
final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
return d.getBytes();
@@ -97,7 +97,7 @@ public double getValueDouble() {
public float getValueFloat() {
if (super.getType() != PRIMITIVE_FLOAT) {
- throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue");
+ throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue");
}
final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
return f.getBytes();
@@ -105,14 +105,14 @@ public float getValueFloat() {
public int getValueInt() {
if (super.getType() != PRIMITIVE_INT) {
- throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue");
+ throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue");
}
return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public long getValueLong() {
if (super.getType() != PRIMITIVE_LONG) {
- throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue");
+ throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue");
}
final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
return j.getBytes();
@@ -120,7 +120,7 @@ public long getValueLong() {
public short getValueShort() {
if (super.getType() != PRIMITIVE_SHORT) {
- throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue");
+ throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue");
}
final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
return (short) s.getBytes();
@@ -128,7 +128,7 @@ public short getValueShort() {
public String getValueString() {
if (super.getType() != STRING) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
index e9ceed21957..bfa9cbf8fcb 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
@@ -40,7 +40,7 @@ public final class SourceFile extends Attribute {
private int sourceFileIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
index 1f8ce5ea410..317638e6b2d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,8 +30,8 @@
/**
* This class represents a stack map attribute used for preverification of Java classes for the
- * Java 2 Micro Edition (J2ME). This attribute is used by the
- * KVM and contained within the Code attribute of a method. See CLDC
+ * Java 2 Micro Edition (J2ME). This attribute is used by the
+ * KVM and contained within the Code attribute of a method. See CLDC
* specification 5.3.1.2
*
*
@@ -46,14 +46,14 @@
* @see Code
* @see StackMapEntry
* @see StackMapType
- * @LastModified: Oct 2020
+ * @LastModified: Sept 2025
*/
public final class StackMap extends Attribute {
private StackMapEntry[] table; // Table of stack map entries
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index of name
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
index 110e30392ab..015083dd066 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
@@ -59,7 +59,7 @@ public final class StackMapEntry implements Node, Cloneable {
private ConstantPool constantPool;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param dataInput Input stream
* @throws IOException if an I/O error occurs.
@@ -75,9 +75,7 @@ public final class StackMapEntry implements Node, Cloneable {
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
byteCodeOffset = dataInput.readUnsignedShort();
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
- } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
- byteCodeOffset = dataInput.readUnsignedShort();
- } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+ } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
byteCodeOffset = dataInput.readUnsignedShort();
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
byteCodeOffset = dataInput.readUnsignedShort();
@@ -167,7 +165,7 @@ public StackMapEntry copy() {
try {
e = (StackMapEntry) clone();
} catch (final CloneNotSupportedException ex) {
- throw new Error("Clone Not Supported");
+ throw new UnsupportedOperationException("Clone Not Supported", ex);
}
e.typesOfLocals = new StackMapType[typesOfLocals.length];
@@ -190,9 +188,7 @@ public void dump(final DataOutputStream file) throws IOException {
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
file.writeShort(byteCodeOffset);
typesOfStackItems[0].dump(file);
- } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
- file.writeShort(byteCodeOffset);
- } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+ } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
file.writeShort(byteCodeOffset);
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
file.writeShort(byteCodeOffset);
@@ -232,7 +228,6 @@ public int getFrameType() {
/**
* Calculate stack map entry size
- *
*/
int getMapEntrySize() {
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
index 4575b31dfce..b93066d53b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
@@ -34,9 +34,9 @@
* @see StackMap
* @see Const
*/
-public final class StackMapType implements Cloneable {
+public final class StackMapType implements Node, Cloneable {
- public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
+ public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY
private byte type;
private int index = -1; // Index to CONSTANT_Class or offset
@@ -53,7 +53,7 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -66,6 +66,18 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
this.constantPool = constantPool;
}
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
+ * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ * @since 6.8.0
+ */
+ @Override
+ public void accept(final Visitor v) {
+ v.visitStackMapType(this);
+ }
+
private byte checkType(final byte type) {
if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
throw new ClassFormatException("Illegal type for StackMapType: " + type);
@@ -98,6 +110,15 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the class name of this StackMapType from the constant pool at index position.
+ * @return the fully qualified name of the class for this StackMapType.
+ * @since 6.8.0
+ */
+ public String getClassName() {
+ return constantPool.constantToString(index, Const.CONSTANT_Class);
+ }
+
/**
* @return Constant pool used by this object.
*/
@@ -129,7 +150,7 @@ private String printIndex() {
if (index < 0) {
return ", class=";
}
- return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
+ return ", class=" + getClassName();
}
if (type == Const.ITEM_NewObject) {
return ", offset=" + index;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
index 3683fd6437e..c7fef8fcebc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
@@ -52,7 +52,7 @@ public Synthetic(final int nameIndex, final int length, final byte[] bytes, fina
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
index 12dbbe4828a..6967dcefd94 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -43,7 +43,7 @@
/**
* Utility functions that do not really belong to any class in particular.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
// @since 6.0 methods are no longer final
public abstract class Utility {
@@ -51,7 +51,7 @@ public abstract class Utility {
/**
* Decode characters into bytes. Used by decode()
*/
- private static class JavaReader extends FilterReader {
+ private static final class JavaReader extends FilterReader {
public JavaReader(final Reader in) {
super(in);
@@ -88,10 +88,10 @@ public int read(final char[] cbuf, final int off, final int len) throws IOExcept
}
/**
- * Encode bytes into valid java identifier characters. Used by
+ * Encode bytes into valid Java identifier characters. Used by
* encode()
*/
- private static class JavaWriter extends FilterWriter {
+ private static final class JavaWriter extends FilterWriter {
public JavaWriter(final Writer out) {
super(out);
@@ -437,7 +437,9 @@ public static String codeToString(final ByteSequence bytes, final ConstantPool c
case Const.NEW:
case Const.CHECKCAST:
buf.append("\t");
- //$FALL-THROUGH$
+ index = bytes.readUnsignedShort();
+ buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
+ break;
case Const.INSTANCEOF:
index = bytes.readUnsignedShort();
buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
@@ -864,7 +866,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
vec.add(typeSignatureToString(signature.substring(index), chopit));
@@ -872,7 +874,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
index += unwrap(CONSUMER_CHARS); // update position
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return vec.toArray(Const.EMPTY_STRING_ARRAY);
}
@@ -903,11 +905,11 @@ public static String methodSignatureReturnType(final String signature, final boo
// Read return type after ')'
index = signature.lastIndexOf(')') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
type = typeSignatureToString(signature.substring(index), chopit);
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return type;
}
@@ -959,7 +961,7 @@ public static String methodSignatureToString(final String signature, final Strin
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
final String paramType = typeSignatureToString(signature.substring(index), chopit);
@@ -985,7 +987,7 @@ public static String methodSignatureToString(final String signature, final Strin
// Read return type after ')'
type = typeSignatureToString(signature.substring(index), chopit);
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
// ignore any throws information in the signature
if (buf.length() > 1) {
@@ -1172,7 +1174,7 @@ public static String signatureToString(final String signature, final boolean cho
type = typeParams + typeSignaturesToString(signature.substring(index), chopit, ')');
index += unwrap(CONSUMER_CHARS); // update position
// add return type
- type = type + typeSignatureToString(signature.substring(index), chopit);
+ type += typeSignatureToString(signature.substring(index), chopit);
index += unwrap(CONSUMER_CHARS); // update position
// ignore any throws information in the signature
return type;
@@ -1237,12 +1239,12 @@ public static byte typeOfMethodSignature(final String signature) throws ClassFor
int index;
try {
if (signature.charAt(0) != '(') {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
index = signature.lastIndexOf(')') + 1;
return typeOfSignature(signature.substring(index));
} catch (final StringIndexOutOfBoundsException e) {
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
@@ -1286,10 +1288,10 @@ public static byte typeOfSignature(final String signature) throws ClassFormatExc
case '*':
return typeOfSignature(signature.substring(1));
default:
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
} catch (final StringIndexOutOfBoundsException e) {
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
@@ -1469,8 +1471,8 @@ public static String typeSignatureToString(final String signature, final boolean
} else {
type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
// update our consumed count by the number of characters the for type argument
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
}
// are there more TypeArguments?
@@ -1490,8 +1492,8 @@ public static String typeSignatureToString(final String signature, final boolean
} else {
type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
// update our consumed count by the number of characters the for type argument
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
}
}
@@ -1508,14 +1510,14 @@ public static String typeSignatureToString(final String signature, final boolean
// update our consumed count by the number of characters the for type argument
// note that this count includes the "L" we added, but that is ok
// as it accounts for the "." we didn't consume
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
return type.toString();
}
if (signature.charAt(consumedChars) != ';') {
throw new ClassFormatException("Invalid signature: " + signature);
}
- wrap(Utility.CONSUMER_CHARS, consumedChars + 1); // remove final ";"
+ wrap(CONSUMER_CHARS, consumedChars + 1); // remove final ";"
return type.toString();
}
case 'S':
@@ -1536,9 +1538,9 @@ public static String typeSignatureToString(final String signature, final boolean
// The rest of the string denotes a ''
type = typeSignatureToString(signature.substring(n), chopit);
// corrected concurrent private static field acess
- // Utility.consumed_chars += consumed_chars; is replaced by:
- final int temp = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, temp);
+ // consumed_chars += consumed_chars; is replaced by:
+ final int temp = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, temp);
return type + brackets.toString();
}
case 'V':
@@ -1552,11 +1554,11 @@ public static String typeSignatureToString(final String signature, final boolean
}
private static int unwrap(final ThreadLocal tl) {
- return tl.get();
+ return tl.get().intValue();
}
private static void wrap(final ThreadLocal tl, final int value) {
- tl.set(value);
+ tl.set(Integer.valueOf(value));
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
index 74cb8400d3e..1f6fe9c96ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
@@ -217,11 +217,32 @@ default void visitNestMembers(final NestMembers obj) {
*/
void visitParameterAnnotation(ParameterAnnotations obj);
+
/**
* @since 6.0
*/
void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
+ /**
+ * Visits a {@link Record} object.
+ *
+ * @param obj Record to visit
+ * @since 6.9.0
+ */
+ default void visitRecord(final Record obj) {
+ // empty
+ }
+
+ /**
+ * Visits a {@link RecordComponentInfo} object.
+ *
+ * @param record component to visit
+ * @since 6.9.0
+ */
+ default void visitRecordComponent(final RecordComponentInfo record) {
+ // noop
+ }
+
void visitSignature(Signature obj);
void visitSourceFile(SourceFile obj);
@@ -230,7 +251,18 @@ default void visitNestMembers(final NestMembers obj) {
void visitStackMapEntry(StackMapEntry obj);
+ /**
+ * Visits a {@link StackMapType} object.
+ *
+ * @param obj object to visit
+ * @since 6.8.0
+ */
+ default void visitStackMapType(final StackMapType obj) {
+ // empty
+ }
+
void visitSynthetic(Synthetic obj);
void visitUnknown(Unknown obj);
+
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
new file mode 100644
index 00000000000..4e8d383bcab
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Classes that describe the structure of a Java class file and a class file parser.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
index 2d7188e9174..db756700085 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,12 +28,12 @@
*
* Stack: ..., arrayref -> ..., length
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ {
/**
- * Get length of array
+ * Gets length of array
*/
public ARRAYLENGTH() {
super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
index bb2e953f850..07171fefde1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,8 +28,10 @@
*
* Stack: ..., objectref -> objectref
*
+ *
+ * @LastModified: Sept 2025
*/
-public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower {
+public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower, StackConsumer {
/**
* Throw exception
@@ -48,6 +50,7 @@ public ATHROW() {
public void accept(final Visitor v) {
v.visitUnconditionalBranch(this);
v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
v.visitATHROW(this);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
index ea01a837175..0fad6ea7389 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
import com.sun.org.apache.bcel.internal.classfile.Attribute;
@@ -37,10 +38,11 @@
import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleParameterAnnotations;
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations;
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations;
+import jdk.xml.internal.Utils;
/**
* @since 6.0
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public class AnnotationEntryGen {
@@ -53,7 +55,7 @@ public class AnnotationEntryGen {
* @param annotationEntryGens An array of AnnotationGen objects
*/
static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) {
- if (annotationEntryGens.length == 0) {
+ if (annotationEntryGens == null && annotationEntryGens.length == 0) {
return Attribute.EMPTY_ARRAY;
}
@@ -255,11 +257,7 @@ public void addElementNameValuePair(final ElementValuePairGen evp) {
}
private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
- final List out = new ArrayList<>();
- for (final ElementValuePair nvp : in) {
- out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries));
- }
- return out;
+ return Utils.streamOfIfNonNull(in).map(nvp -> new ElementValuePairGen(nvp, cpool, copyPoolEntries)).collect(Collectors.toList());
}
public void dump(final DataOutputStream dos) throws IOException {
@@ -286,18 +284,20 @@ public int getTypeIndex() {
}
public final String getTypeName() {
- return getTypeSignature();// BCELBUG: Should I use this instead?
+ return getTypeSignature(); // BCELBUG: Should I use this instead?
// Utility.signatureToString(getTypeSignature());
}
public final String getTypeSignature() {
- // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex);
+ // ConstantClass c = (ConstantClass) cpool.getConstant(typeIndex);
final ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex/* c.getNameIndex() */);
return utf8.getBytes();
}
/**
- * Returns list of ElementNameValuePair objects
+ * Returns list of ElementNameValuePair objects.
+ *
+ * @return list of ElementNameValuePair objects.
*/
public List getValues() {
return evs;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
index 71374877efe..59b774a9afc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,12 +24,15 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.classfile.ArrayElementValue;
import com.sun.org.apache.bcel.internal.classfile.ElementValue;
+import jdk.xml.internal.Utils;
/**
* @since 6.0
+ * @LastModified: Sept 2025
*/
public class ArrayElementValueGen extends ElementValueGen {
// J5TODO: Should we make this an array or a list? A list would be easier to
@@ -46,7 +48,7 @@ public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen
evalues = new ArrayList<>();
final ElementValue[] in = value.getElementValuesArray();
for (final ElementValue element : in) {
- evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries));
+ evalues.add(copy(element, cpool, copyPoolEntries));
}
}
@@ -55,15 +57,12 @@ public ArrayElementValueGen(final ConstantPoolGen cp) {
evalues = new ArrayList<>();
}
- public ArrayElementValueGen(final int type, final ElementValue[] datums, final ConstantPoolGen cpool) {
+ public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) {
super(type, cpool);
if (type != ARRAY) {
throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type);
}
- this.evalues = new ArrayList<>();
- for (final ElementValue datum : datums) {
- evalues.add(ElementValueGen.copy(datum, cpool, true));
- }
+ this.evalues = Utils.streamOfIfNonNull(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList());
}
public void addElement(final ElementValueGen gen) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
index 138999ebe90..78a676e875e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -24,6 +23,8 @@
/**
* Denotes array type, such as int[][]
+ *
+ * @LastModified: Sept 2025
*/
public final class ArrayType extends ReferenceType {
@@ -43,7 +44,7 @@ public ArrayType(final byte type, final int dimensions) {
/**
* Convenience constructor for reference array type, e.g. Object[]
*
- * @param className complete name of class (java.lang.String, e.g.)
+ * @param className complete name of class ({@link String}, for example)
* @param dimensions array dimensions
*/
public ArrayType(final String className, final int dimensions) {
@@ -56,6 +57,7 @@ public ArrayType(final String className, final int dimensions) {
* @param type type of array (may be an array itself)
* @param dimensions array dimensions
*/
+ @SuppressWarnings("deprecation") //signature
public ArrayType(final Type type, final int dimensions) {
super(Const.T_ARRAY, "");
if (dimensions < 1 || dimensions > Const.MAX_BYTE) {
@@ -79,7 +81,7 @@ public ArrayType(final Type type, final int dimensions) {
buf.append('[');
}
buf.append(basicType.getSignature());
- super.setSignature(buf.toString());
+ this.signature = buf.toString();
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
index 91ab9ac5463..f489f9a7658 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
@@ -63,7 +63,7 @@ public InstructionHandle getTarget() {
}
/**
- * Set new contents. Old instruction is disposed and may not be used anymore.
+ * Sets new contents. Old instruction is disposed and may not be used anymore.
*/
@Override // This is only done in order to apply the additional type check; could be merged with super impl.
public void setInstruction(final Instruction i) { // TODO could be package-protected?
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
index 1dfd244141a..ff45e5cde93 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -35,7 +35,7 @@
* @see LDC
* @see INVOKEVIRTUAL
*
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
@@ -104,7 +104,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the index to constant pool.
+ * Sets the index to constant pool.
*
* @param index in constant pool.
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
index 1c1c032dbd5..8e024eebaa4 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
@@ -48,12 +48,12 @@ public ClassElementValueGen(final ClassElementValue value, final ConstantPoolGen
}
protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) {
- super(ElementValueGen.CLASS, cpool);
+ super(CLASS, cpool);
this.idx = typeIdx;
}
public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) {
- super(ElementValueGen.CLASS, cpool);
+ super(CLASS, cpool);
// this.idx = cpool.addClass(t);
idx = cpool.addUtf8(t.getSignature());
}
@@ -67,9 +67,9 @@ public void dump(final DataOutputStream dos) throws IOException {
public String getClassString() {
final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx);
return cu8.getBytes();
- // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx);
+ // ConstantClass c = (ConstantClass) getConstantPool().getConstant(idx);
// ConstantUtf8 utf8 =
- // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex());
+ // (ConstantUtf8) getConstantPool().getConstant(c.getNameIndex());
// return utf8.getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
index acaf4519567..debf930fe90 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,40 +40,37 @@
import com.sun.org.apache.bcel.internal.util.BCELComparator;
/**
- * Template class for building up a java class. May be initialized with an existing java class (file).
+ * Template class for building up a java class. May be initialized with an existing Java class (file).
*
* @see JavaClass
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ClassGen extends AccessFlags implements Cloneable {
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final ClassGen THIS = (ClassGen) o1;
- final ClassGen THAT = (ClassGen) o2;
- return Objects.equals(THIS.getClassName(), THAT.getClassName());
+ public boolean equals(final ClassGen a, final ClassGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName());
}
@Override
- public int hashCode(final Object o) {
- final ClassGen THIS = (ClassGen) o;
- return THIS.getClassName().hashCode();
+ public int hashCode(final ClassGen o) {
+ return o != null ? Objects.hashCode(o.getClassName()) : 0;
}
};
/**
* @return Comparison strategy object
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
* @param comparator Comparison strategy object
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -101,7 +98,7 @@ public static void setComparator(final BCELComparator comparator) {
private List observers;
/**
- * Initialize with existing class.
+ * Constructs a new instance from an existing class.
*
* @param clazz JavaClass object (e.g. read from file)
*/
@@ -118,15 +115,26 @@ public ClassGen(final JavaClass clazz) {
final Attribute[] attributes = clazz.getAttributes();
// J5TODO: Could make unpacking lazy, done on first reference
final AnnotationEntryGen[] annotations = unpackAnnotations(attributes);
- Collections.addAll(interfaceList, clazz.getInterfaceNames());
- for (final Attribute attribute : attributes) {
- if (!(attribute instanceof Annotations)) {
- addAttribute(attribute);
+ final String[] interfaceNames = clazz.getInterfaceNames();
+ if (interfaceNames != null) {
+ Collections.addAll(interfaceList, interfaceNames);
+ }
+ if (attributes != null) {
+ for (final Attribute attribute : attributes) {
+ if (!(attribute instanceof Annotations)) {
+ addAttribute(attribute);
+ }
}
}
Collections.addAll(annotationList, annotations);
- Collections.addAll(methodList, clazz.getMethods());
- Collections.addAll(fieldList, clazz.getFields());
+ final Method[] methods = clazz.getMethods();
+ if (methods != null) {
+ Collections.addAll(methodList, methods);
+ }
+ final Field[] fields = clazz.getFields();
+ if (fields != null) {
+ Collections.addAll(fieldList, fields);
+ }
}
/**
@@ -242,7 +250,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -282,7 +290,7 @@ public Method containsMethod(final String name, final String signature) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof ClassGen && bcelComparator.equals(this, (ClassGen) obj);
}
// J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
@@ -379,7 +387,7 @@ public int getSuperclassNameIndex() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name.
*
* @see Object#hashCode()
*/
@@ -478,7 +486,7 @@ public void setConstantPool(final ConstantPoolGen constantPool) {
}
/**
- * Set major version number of class file, default value is 45 (JDK 1.1)
+ * Sets major version number of class file, default value is 45 (JDK 1.1)
*
* @param major major version number
*/
@@ -492,11 +500,13 @@ public void setMethodAt(final Method method, final int pos) {
public void setMethods(final Method[] methods) {
methodList.clear();
- Collections.addAll(methodList, methods);
+ if (methods != null) {
+ Collections.addAll(methodList, methods);
+ }
}
/**
- * Set minor version number of class file, default value is 3 (JDK 1.1)
+ * Sets minor version number of class file, default value is 3 (JDK 1.1)
*
* @param minor minor version number
*/
@@ -515,17 +525,19 @@ public void setSuperclassNameIndex(final int superclassNameIndex) {
}
/**
- * Look for attributes representing annotations and unpack them.
+ * Unpacks attributes representing annotations.
*/
- private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) {
+ private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attributes) {
final List annotationGenObjs = new ArrayList<>();
- for (final Attribute attr : attrs) {
- if (attr instanceof RuntimeVisibleAnnotations) {
- final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
- rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
- } else if (attr instanceof RuntimeInvisibleAnnotations) {
- final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
- ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ if (attributes != null) {
+ for (final Attribute attr : attributes) {
+ if (attr instanceof RuntimeVisibleAnnotations) {
+ final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
+ rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ } else if (attr instanceof RuntimeInvisibleAnnotations) {
+ final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
+ ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ }
}
}
return annotationGenObjs.toArray(AnnotationEntryGen.EMPTY_ARRAY);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
index fa660954d15..2518131ccee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
@@ -63,7 +63,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -81,7 +81,7 @@ public ObjectType getCatchType() {
}
/**
- * Get CodeException object.
+ * Gets CodeException object.
*
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
* has been called for the instruction list.
@@ -120,7 +120,7 @@ public void setCatchType(final ObjectType catchType) {
}
/*
- * Set end of handler
+ * Sets end of handler
*
* @param endPc End of handled region (inclusive)
*/
@@ -130,7 +130,7 @@ public void setEndPC(final InstructionHandle endPc) { // TODO could be package-p
}
/*
- * Set handler code
+ * Sets handler code
*
* @param handlerPc Start of handler
*/
@@ -140,7 +140,7 @@ public void setHandlerPC(final InstructionHandle handlerPc) { // TODO could be p
}
/*
- * Set start of handler
+ * Sets start of handler
*
* @param startPc Start of handled region (inclusive)
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
index bdc9c517a86..878f392b6b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
@@ -44,7 +44,7 @@ public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpo
// Could assert nvp.getNameString() points to the same thing as
// constantPoolGen.getConstant(nvp.getNameIndex())
// if
- // (!nvp.getNameString().equals(((ConstantUtf8)constantPoolGen.getConstant(nvp.getNameIndex())).getBytes()))
+ // (!nvp.getNameString().equals(((ConstantUtf8) constantPoolGen.getConstant(nvp.getNameIndex())).getBytes()))
// {
// throw new IllegalArgumentException("envp buggered");
// }
@@ -86,7 +86,7 @@ public int getNameIndex() {
}
public final String getNameString() {
- // ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx);
+ // ConstantString cu8 = (ConstantString) constantPoolGen.getConstant(nameIdx);
return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
index 95ac794f2d7..95c00ed3813 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
@@ -40,10 +40,8 @@ public class EnumElementValueGen extends ElementValueGen {
public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
super(ENUM_CONSTANT, cpool);
if (copyPoolEntries) {
- typeIdx = cpool.addUtf8(value.getEnumTypeString());// was
- // addClass(value.getEnumTypeString());
- valueIdx = cpool.addUtf8(value.getEnumValueString()); // was
- // addString(value.getEnumValueString());
+ typeIdx = cpool.addUtf8(value.getEnumTypeString()); // was addClass(value.getEnumTypeString());
+ valueIdx = cpool.addUtf8(value.getEnumValueString()); // was addString(value.getEnumValueString());
} else {
typeIdx = value.getTypeIndex();
valueIdx = value.getValueIndex();
@@ -55,7 +53,7 @@ public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen c
* This ctor is used for deserialization
*/
protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) {
- super(ElementValueGen.ENUM_CONSTANT, cpool);
+ super(ENUM_CONSTANT, cpool);
if (super.getElementValueType() != ENUM_CONSTANT) {
throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType());
}
@@ -64,9 +62,9 @@ protected EnumElementValueGen(final int typeIdx, final int valueIdx, final Const
}
public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) {
- super(ElementValueGen.ENUM_CONSTANT, cpool);
- typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t);
- valueIdx = cpool.addUtf8(value);// was addString(value);
+ super(ENUM_CONSTANT, cpool);
+ typeIdx = cpool.addUtf8(t.getSignature()); // was addClass(t);
+ valueIdx = cpool.addUtf8(value); // was addString(value);
}
@Override
@@ -90,9 +88,9 @@ public ElementValue getElementValue() {
public String getEnumTypeString() {
// Constant cc = getConstantPool().getConstant(typeIdx);
// ConstantClass cu8 =
- // (ConstantClass)getConstantPool().getConstant(typeIdx);
+ // (ConstantClass) getConstantPool().getConstant(typeIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes();
// return Utility.signatureToString(cu8.getBytes());
}
@@ -100,9 +98,9 @@ public String getEnumTypeString() {
public String getEnumValueString() {
return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes();
// ConstantString cu8 =
- // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // (ConstantString) getConstantPool().getConstant(valueIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
public int getTypeIndex() {
@@ -118,8 +116,8 @@ public String stringifyValue() {
final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx);
return cu8.getBytes();
// ConstantString cu8 =
- // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // (ConstantString) getConstantPool().getConstant(valueIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
index 86a0cad256c..2a488c85ede 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
@@ -23,7 +23,7 @@
/**
* Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite
- * the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted.
+ * the truth as such; because all instructions may throw a {@link VirtualMachineError}. These exceptions are omitted.
*
* The Lava Language Specification specifies exactly which RUN-TIME and which LINKING exceptions each
* instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
index 9d1f4d41d93..30786370d29 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,37 +40,34 @@
* to a field (which must of course be compatible with to the declared type).
*
* @see Field
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class FieldGen extends FieldGenOrMethodGen {
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final FieldGen THIS = (FieldGen) o1;
- final FieldGen THAT = (FieldGen) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final FieldGen a, final FieldGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final FieldGen THIS = (FieldGen) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final FieldGen o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -81,8 +78,8 @@ public static void setComparator(final BCELComparator comparator) {
/**
* Instantiate from existing field.
*
- * @param field Field object
- * @param cp constant pool (must contain the same entries as the field's constant pool)
+ * @param field Field object.
+ * @param cp constant pool (must contain the same entries as the field's constant pool).
*/
public FieldGen(final Field field, final ConstantPoolGen cp) {
this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
@@ -187,11 +184,11 @@ public FieldGen copy(final ConstantPoolGen cp) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof FieldGen && bcelComparator.equals(this, (FieldGen) obj);
}
/**
- * Get field object after having set up all necessary values.
+ * Gets field object after having set up all necessary values.
*/
public Field getField() {
final String signature = getSignature();
@@ -207,10 +204,7 @@ public Field getField() {
}
public String getInitValue() {
- if (value != null) {
- return value.toString();
- }
- return null;
+ return Objects.toString(value, null);
}
@Override
@@ -219,7 +213,7 @@ public String getSignature() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
* signature.
*
* @see Object#hashCode()
@@ -295,7 +289,7 @@ public void setInitValue(final short s) {
}
/**
- * Set (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically.
+ * Sets (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically.
*/
public void setInitValue(final String str) {
checkType(ObjectType.getInstance("java.lang.String"));
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
index 6555392e9d4..bc1fbc8627e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,7 +30,7 @@
/**
* Super class for FieldGen and MethodGen objects, since they have some methods in common!
*
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
@@ -67,8 +67,10 @@ protected FieldGenOrMethodGen(final int accessFlags) { // TODO could this be pac
super(accessFlags);
}
- protected void addAll(final Attribute[] attrs) {
- Collections.addAll(attributeList, attrs);
+ protected void addAll(final Attribute[] attributes) {
+ if (attributes != null) {
+ Collections.addAll(attributeList, attributes);
+ }
}
/**
@@ -93,7 +95,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
index 1c646f48292..87ba4cb913e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
@@ -53,7 +53,6 @@ protected FieldOrMethod(final short opcode, final int index) {
* generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an
* array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
* distinguishes between class types and array types.
- *
*/
@Deprecated
public String getClassName(final ConstantPoolGen cpg) {
@@ -89,6 +88,9 @@ public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
if (rt instanceof ObjectType) {
return (ObjectType) rt;
}
+ if (rt instanceof ArrayType) {
+ return Type.OBJECT;
+ }
throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType");
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
index 5effd7edcd9..b3eb14a9ddf 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
@@ -25,7 +25,6 @@
*
* Stack: ... -> ...,
*
- *
*/
public class ICONST extends Instruction implements ConstantPushInstruction {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
index 2865a158de2..998d072e067 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -37,7 +37,7 @@
* @see The
* invokedynamic instruction in The Java Virtual Machine Specification
* @since 6.0
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class INVOKEDYNAMIC extends InvokeInstruction {
@@ -104,11 +104,11 @@ public Class>[] getExceptions() {
}
/**
- * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, as that is the only type we can
+ * Since InvokeDynamic doesn't refer to a reference type, just return {@link Object}, as that is the only type we can
* say for sure the reference will be.
*
* @param cpg the ConstantPoolGen used to create the instruction
- * @return an ObjectType for java.lang.Object
+ * @return an ObjectType for {@link Object}
* @since 6.1
*/
@Override
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
index 16c8e2444b4..a7124409f12 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,7 +29,7 @@
/**
* Abstract super class for all Java byte codes.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public abstract class Instruction implements Cloneable {
@@ -461,7 +461,7 @@ public int consumeStack(final ConstantPoolGen cpg) {
public Instruction copy() {
Instruction i = null;
// "Constant" instruction, no need to duplicate
- if (InstructionConst.getInstruction(this.getOpcode()) != null) {
+ if (InstructionConst.getInstruction(getOpcode()) != null) {
i = this;
} else {
try {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
index 439268e35eb..7b95bfc99b1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
@@ -170,7 +170,7 @@ public final class InstructionConst {
public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2);
/**
- * Get object via its opcode, for immutable instructions like branch instructions entries are set to null.
+ * Gets object via its opcode, for immutable instructions like branch instructions entries are set to null.
*/
static final Instruction[] INSTRUCTIONS = new Instruction[256];
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
index 5e9220354c3..3c4b3e9f9da 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,11 +30,11 @@
*
* @see Const
* @see InstructionConst
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class InstructionFactory {
- private static class MethodObject {
+ private static final class MethodObject {
final Type[] argTypes;
final Type resultType;
@@ -53,10 +53,12 @@ private static class MethodObject {
private static final String FQCN_STRING_BUFFER = "java.lang.StringBuffer";
- // N.N. These must agree with the order of Constants.T_CHAR through T_LONG
- private static final String[] shortNames = {"C", "F", "D", "B", "S", "I", "L"};
+ /**
+ * These must agree with the order of Constants.T_CHAR through T_LONG.
+ */
+ private static final String[] SHORT_NAMES = {"C", "F", "D", "B", "S", "I", "L"};
- private static final MethodObject[] appendMethodObjects = {
+ private static final MethodObject[] APPEND_METHOD_OBJECTS = {
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.STRING }),
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.OBJECT }), null, null, // indices 2, 3
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }),
@@ -484,7 +486,7 @@ public InstructionFactory(final ConstantPoolGen cp) {
public Instruction createAppend(final Type type) {
final byte t = type.getType();
if (isString(type)) {
- return createInvoke(appendMethodObjects[0], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[0], Const.INVOKEVIRTUAL);
}
switch (t) {
case Const.T_BOOLEAN:
@@ -495,10 +497,10 @@ public Instruction createAppend(final Type type) {
case Const.T_SHORT:
case Const.T_INT:
case Const.T_LONG:
- return createInvoke(appendMethodObjects[t], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[t], Const.INVOKEVIRTUAL);
case Const.T_ARRAY:
case Const.T_OBJECT:
- return createInvoke(appendMethodObjects[1], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[1], Const.INVOKEVIRTUAL);
default:
throw new IllegalArgumentException("No append for this type? " + type);
}
@@ -515,7 +517,7 @@ public Instruction createCast(final Type srcType, final Type destType) {
if (dest == Const.T_LONG && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) {
src = Const.T_INT;
}
- final String name = "com.sun.org.apache.bcel.internal.generic." + shortNames[src - Const.T_CHAR] + "2" + shortNames[dest - Const.T_CHAR];
+ final String name = "com.sun.org.apache.bcel.internal.generic." + SHORT_NAMES[src - Const.T_CHAR] + "2" + SHORT_NAMES[dest - Const.T_CHAR];
Instruction i = null;
try {
i = (Instruction) Class.forName(name).getDeclaredConstructor().newInstance();;
@@ -642,8 +644,10 @@ public InvokeInstruction createInvoke(final String className, final String name,
int index;
int nargs = 0;
final String signature = Type.getMethodSignature(retType, argTypes);
- for (final Type argType : argTypes) {
- nargs += argType.getSize();
+ if (argTypes != null) {
+ for (final Type argType : argTypes) {
+ nargs += argType.getSize();
+ }
}
if (useInterface) {
index = cp.addInterfaceMethodref(className, name, signature);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
index 5e962354d16..2c94b770265 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -38,7 +38,7 @@
* @see Instruction
* @see BranchHandle
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class InstructionHandle {
@@ -118,7 +118,7 @@ public void addTargeter(final InstructionTargeter t) {
if (targeters == null) {
targeters = new HashSet<>();
}
- // if(!targeters.contains(t))
+ // if (!targeters.contains(t))
targeters.add(t);
}
@@ -135,15 +135,12 @@ void dispose() {
}
/**
- * Get attribute of an instruction handle.
+ * Gets attribute of an instruction handle.
*
* @param key the key object to store/retrieve the attribute
*/
public Object getAttribute(final Object key) {
- if (attributes != null) {
- return attributes.get(key);
- }
- return null;
+ return attributes != null ? attributes.get(key) : null;
}
/**
@@ -247,7 +244,7 @@ final InstructionHandle setNext(final InstructionHandle next) {
}
/**
- * Set the position, i.e., the byte code offset of the contained instruction.
+ * Sets the position, i.e., the byte code offset of the contained instruction.
*/
void setPosition(final int pos) {
i_position = pos;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
index 7ffc3a8228e..579efc9fe3b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -33,6 +33,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.Constant;
import com.sun.org.apache.bcel.internal.util.ByteSequence;
+import jdk.xml.internal.Utils;
/**
* This class is a container for a list of Instruction objects. Instructions can be
@@ -46,7 +47,7 @@
* @see Instruction
* @see InstructionHandle
* @see BranchHandle
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class InstructionList implements Iterable {
@@ -60,23 +61,25 @@ public class InstructionList implements Iterable {
* @return target position's instruction handle if available
*/
public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) {
- int l = 0;
- int r = count - 1;
- /*
- * Do a binary search since the pos array is orderd.
- */
- do {
- final int i = l + r >>> 1;
- final int j = pos[i];
- if (j == target) {
- return ihs[i];
- }
- if (target < j) {
- r = i - 1;
- } else {
- l = i + 1;
- }
- } while (l <= r);
+ if (ihs != null && pos != null) {
+ int l = 0;
+ int r = count - 1;
+ /*
+ * Do a binary search since the pos array is orderd.
+ */
+ do {
+ final int i = l + r >>> 1;
+ final int j = pos[i];
+ if (j == target) {
+ return ihs[i];
+ }
+ if (target < j) {
+ r = i - 1;
+ } else {
+ l = i + 1;
+ }
+ } while (l <= r);
+ }
return null;
}
@@ -513,7 +516,7 @@ public void dispose() {
}
/**
- * Get instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly
+ * Gets instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly
* initialized from a byte array or setPositions() has been called before this method.
*
* @param pos byte code position to search for
@@ -605,7 +608,7 @@ public InstructionHandle[] getInstructionHandles() {
}
/**
- * Get positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from
+ * Gets positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from
* an byte code array, or that setPositions() has been called. Otherwise this may be inaccurate.
*
* @return array containing all instruction's offset in byte code
@@ -959,7 +962,7 @@ public void redirectBranches(final InstructionHandle oldTarget, final Instructio
* @see MethodGen
*/
public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
- for (final CodeExceptionGen exception : exceptions) {
+ Utils.streamOfIfNonNull(exceptions).forEach(exception -> {
if (exception.getStartPC() == oldTarget) {
exception.setStartPC(newTarget);
}
@@ -969,7 +972,7 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final
if (exception.getHandlerPC() == oldTarget) {
exception.setHandlerPC(newTarget);
}
- }
+ });
}
/**
@@ -981,16 +984,14 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final
* @see MethodGen
*/
public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
- for (final LocalVariableGen element : lg) {
- final InstructionHandle start = element.getStart();
- final InstructionHandle end = element.getEnd();
- if (start == oldTarget) {
+ Utils.streamOfIfNonNull(lg).forEach(element -> {
+ if (element.getStart() == oldTarget) {
element.setStart(newTarget);
}
- if (end == oldTarget) {
+ if (element.getEnd() == oldTarget) {
element.setEnd(newTarget);
}
- }
+ });
}
/**
@@ -1120,7 +1121,7 @@ public void setPositions(final boolean check) { // called by code in other packa
ih.setPosition(index);
pos[count++] = index;
/*
- * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
+ * Gets an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
* depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH).
*/
switch (i.getOpcode()) {
@@ -1132,11 +1133,14 @@ public void setPositions(final boolean check) { // called by code in other packa
case Const.LOOKUPSWITCH:
maxAdditionalBytes += 3;
break;
+ default:
+ // TODO should this be an error?
+ break;
}
index += i.getLength();
}
/*
- * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that
+ * Pass 2: Expand the variable-length (Branch) Instructions depending on the target offset (short or int) and ensure that
* branch targets are within this list.
*/
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
@@ -1152,8 +1156,7 @@ public void setPositions(final boolean check) { // called by code in other packa
pos[count++] = index;
index += i.getLength();
}
- bytePositions = new int[count]; // Trim to proper size
- System.arraycopy(pos, 0, bytePositions, 0, count);
+ bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
index 5146408ef49..0681476b5ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
@@ -22,7 +22,7 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Denote that a class targets InstructionHandles within an InstructionList. Namely the following implementers:
+ * Denotes that a class targets InstructionHandles within an InstructionList.
*
* @see BranchHandle
* @see LocalVariableGen
@@ -33,9 +33,12 @@ public interface InstructionTargeter {
// static final InstructionTargeter[] EMPTY_ARRAY = new InstructionTargeter[0];
/**
- * Checks whether this targeter targets the specified instruction handle.
+ * Tests whether this targeter targets the specified instruction handle.
+ *
+ * @param instructionHandle the instruction handle to test.
+ * @return whether this targeter targets the specified instruction handle.
*/
- boolean containsTarget(InstructionHandle ih);
+ boolean containsTarget(InstructionHandle instructionHandle);
/**
* Replaces the target of this targeter from this old handle to the new handle.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
index c517b492f0a..188ac95f6ef 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
@@ -27,7 +27,6 @@
*
- *
*/
public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
index d95bade23bd..13ca0a84cfa 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
@@ -94,6 +94,8 @@ public Type getType(final ConstantPoolGen cpg) {
return Type.INT;
case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class:
return Type.CLASS;
+ case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic:
+ return Type.OBJECT;
default: // Never reached
throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
}
@@ -113,7 +115,10 @@ public Object getValue(final ConstantPoolGen cpg) {
case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class:
final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex();
c = cpg.getConstantPool().getConstant(nameIndex);
- return Type.getType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes());
+ return Type.getType(Type.internalTypeNameToSignature(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()));
+ case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic:
+ // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it?
+ return c;
default: // Never reached
throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
}
@@ -129,7 +134,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the index to constant pool and adjust size.
+ * Sets the index to constant pool and adjust size.
*/
@Override
public final void setIndex(final int index) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
index 3773c21e7b3..68bb2abf513 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
@@ -54,7 +54,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -71,7 +71,7 @@ public InstructionHandle getInstruction() {
}
/**
- * Get LineNumber attribute.
+ * Gets LineNumber attribute.
*
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
* has been called for the instruction list.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
index 830564d42c9..71cfa0cf1c2 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
@@ -85,7 +85,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
index 67184c0b9f1..f952a65880b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,7 +28,7 @@
/**
* Abstract super class for instructions dealing with local variables.
*
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
@@ -162,7 +162,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the local variable index. also updates opcode and length TODO Why?
+ * Sets the local variable index. also updates opcode and length TODO Why?
*
* @see #setIndexOnly(int)
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
index f6e8333be79..be09b0a5159 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Stack;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
@@ -46,6 +47,7 @@
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import com.sun.org.apache.bcel.internal.util.BCELComparator;
+import jdk.xml.internal.Utils;
/**
* Template class for building up a method. This is done by defining exception handlers, adding thrown exceptions, local
@@ -57,7 +59,7 @@
*
* @see InstructionList
* @see Method
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class MethodGen extends FieldGenOrMethodGen {
@@ -102,19 +104,16 @@ static final class BranchTarget {
}
}
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o1;
- final FieldGenOrMethodGen THAT = (FieldGenOrMethodGen) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final FieldGenOrMethodGen a, final FieldGenOrMethodGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final FieldGenOrMethodGen o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
@@ -127,9 +126,9 @@ private static byte[] getByteCodes(final Method method) {
}
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
@@ -206,9 +205,9 @@ public static int getMaxStack(final ConstantPoolGen cp, final InstructionList il
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -636,7 +635,7 @@ private void ensureExistingParameterAnnotationsUnpacked() {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof FieldGenOrMethodGen && bcelComparator.equals(this, (FieldGenOrMethodGen) obj);
}
// J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this
@@ -790,7 +789,7 @@ public int getMaxStack() {
}
/**
- * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method
+ * Gets method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method
* (the same applies for max locals).
*
* @return method object
@@ -888,7 +887,7 @@ public String getSignature() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR
* signature.
*
* @see Object#hashCode()
@@ -899,11 +898,7 @@ public int hashCode() {
}
private List makeMutableVersion(final AnnotationEntry[] mutableArray) {
- final List result = new ArrayList<>();
- for (final AnnotationEntry element : mutableArray) {
- result.add(new AnnotationEntryGen(element, getConstantPool(), false));
- }
- return result;
+ return Utils.streamOfIfNonNull(mutableArray).map(ae -> new AnnotationEntryGen(ae, getConstantPool(), false)).collect(Collectors.toList());
}
/**
@@ -1027,10 +1022,8 @@ public void removeObserver(final MethodObserver o) {
*
* @since 6.5.0
*/
- public void removeRuntimeAttributes(final Attribute[] attrs) {
- for (final Attribute attr : attrs) {
- removeAttribute(attr);
- }
+ public void removeRuntimeAttributes(final Attribute[] attributes) {
+ Utils.streamOfIfNonNull(attributes).forEach(this::removeAttribute);
}
public void setArgumentName(final int i, final String name) {
@@ -1038,7 +1031,7 @@ public void setArgumentName(final int i, final String name) {
}
public void setArgumentNames(final String[] argNames) {
- this.argNames = argNames;
+ this.argNames = Utils.createEmptyArrayIfNull(argNames, String[].class);
}
public void setArgumentType(final int i, final Type type) {
@@ -1046,7 +1039,7 @@ public void setArgumentType(final int i, final Type type) {
}
public void setArgumentTypes(final Type[] argTypes) {
- this.argTypes = argTypes;
+ this.argTypes = argTypes != null ? argTypes : Type.NO_ARGS;
}
public void setClassName(final String className) { // TODO could be package-protected?
@@ -1084,7 +1077,7 @@ public void setMaxLocals() { // TODO could be package-protected? (some tests wou
}
/**
- * Set maximum number of local variables.
+ * Sets maximum number of local variables.
*/
public void setMaxLocals(final int m) {
maxLocals = m;
@@ -1102,7 +1095,7 @@ public void setMaxStack() { // TODO could be package-protected? (some tests woul
}
/**
- * Set maximum stack size for this method.
+ * Sets maximum stack size for this method.
*/
public void setMaxStack(final int m) { // TODO could be package-protected?
maxStack = m;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
index 46378a1b71e..622a3cdd961 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
@@ -27,7 +27,7 @@
import com.sun.org.apache.bcel.internal.classfile.Utility;
/**
- * Denotes reference such as java.lang.String.
+ * Denotes reference such as {@link String}.
*/
public class ObjectType extends ReferenceType {
@@ -47,7 +47,7 @@ public static ObjectType getInstance(final String className) {
/**
* Constructs a new instance.
*
- * @param className fully qualified class name, e.g. java.lang.String
+ * @param className fully qualified class name, e.g. {@link String}
*/
public ObjectType(final String className) {
super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";");
@@ -151,7 +151,7 @@ public boolean referencesInterfaceExact() throws ClassNotFoundException {
* @throws ClassNotFoundException if any of this class's superclasses can't be found
*/
public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException {
- if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
+ if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
return false;
}
return Repository.instanceOf(this.className, superclass.className);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
index a7cacc7c165..99a1efbed16 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
@@ -110,7 +110,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set index of local variable containg the return address
+ * Sets index of local variable containg the return address
*/
@Override
public final void setIndex(final int n) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
index fe75792e213..9b94a1dcf2d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
@@ -42,10 +42,10 @@ protected ReferenceType(final byte t, final String s) {
/**
* This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an
- * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t
- * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
- * "this" or t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an
- * interface, then Type.OBJECT is returned. If not all of the two classes' superclasses cannot be found, "null" is
+ * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t
+ * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
+ * "this" or t is an ArrayType, then {@link #OBJECT} is returned. If "this" or t is a ReferenceType referencing an
+ * interface, then {@link #OBJECT} is returned. If not all of the two classes' superclasses cannot be found, "null" is
* returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
*
* @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics.
@@ -53,46 +53,46 @@ protected ReferenceType(final byte t, final String s) {
*/
@Deprecated
public ReferenceType firstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t;
}
- if (t.equals(Type.NULL) || this.equals(t)) {
+ if (t.equals(NULL) || equals(t)) {
return this;
/*
- * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also
- * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's
- * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :)
+ * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also
+ * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's
+ * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :)
*/
}
if (this instanceof ArrayType || t instanceof ArrayType) {
- return Type.OBJECT;
- // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ return OBJECT;
+ // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType?
}
return getFirstCommonSuperclassInternal(t);
}
/**
* This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an
- * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t
- * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
- * "this" or t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the
+ * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t
+ * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
+ * "this" or t is an ArrayType, then {@link #OBJECT} is returned; unless their dimensions match. Then an ArrayType of the
* same number of dimensions is returned, with its basic type being the first common super class of the basic types of
- * "this" and t. If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of
+ * "this" and t. If "this" or t is a ReferenceType referencing an interface, then {@link #OBJECT} is returned. If not all of
* the two classes' superclasses cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The
* Bytecode Verifier".
*
* @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter
*/
public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t;
}
- if (t.equals(Type.NULL) || this.equals(t)) {
+ if (t.equals(NULL) || equals(t)) {
return this;
/*
- * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also
- * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's
- * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :)
+ * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also
+ * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's
+ * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :)
*/
}
/* This code is from a bug report by Konstantin Shagin */
@@ -106,8 +106,8 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas
}
}
if (this instanceof ArrayType || t instanceof ArrayType) {
- return Type.OBJECT;
- // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ return OBJECT;
+ // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType?
}
return getFirstCommonSuperclassInternal(t);
}
@@ -115,7 +115,7 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas
private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) throws ClassNotFoundException {
if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact()
|| t instanceof ObjectType && ((ObjectType) t).referencesInterfaceExact()) {
- return Type.OBJECT;
+ return OBJECT;
// TODO: The above line is correct comparing to the vmspec2. But one could
// make class file verification a bit stronger here by using the notion of
// superinterfaces or even castability or assignment compatibility.
@@ -142,7 +142,7 @@ private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) th
}
}
}
- // Huh? Did you ask for Type.OBJECT's superclass??
+ // Huh? Did you ask for OBJECT's superclass??
return null;
}
@@ -158,7 +158,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
return false;
}
final ReferenceType T = (ReferenceType) t;
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return true; // This is not explicitly stated, but clear. Isn't it?
}
/*
@@ -169,7 +169,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
* If T is a class type, then this must be the same class as T, or this must be a subclass of T;
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact()
- && (this.equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
+ && (equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
return true;
}
/*
@@ -187,14 +187,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/*
* If T is a class type, then T must be Object (2.4.7).
*/
- if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) {
+ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
return true;
}
/*
* If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2).
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()
- && (this.equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
+ && (equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
return true;
}
}
@@ -205,7 +205,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/*
* If T is a class type, then T must be Object (2.4.7).
*/
- if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) {
+ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
return true;
}
/*
@@ -246,14 +246,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/**
* Return true iff this type is castable to another type t as defined in the JVM specification. The case where this is
- * Type.NULL is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST
+ * {@link #NULL} is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST
* doesn't throw a ClassCastException when casting a null reference to any Object, true is returned in this case.
*
* @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be
* found
*/
public boolean isCastableTo(final Type t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible()
}
return isAssignmentCompatibleWith(t);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
index aed1626ec0d..f929176c174 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
@@ -95,7 +95,7 @@ public SWITCH(final int[] match, final InstructionHandle[] targets, final Instru
* @param maxGap maximum gap that may between case branches
*/
public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int maxGap) {
- int[] matchClone = match.clone();
+ final int[] matchClone = match.clone();
final InstructionHandle[] targetsClone = targets.clone();
final int matchLength = match.length;
if (matchLength < 2) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
index a90e795e99f..a3086ac1664 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -33,7 +33,7 @@
* @see LOOKUPSWITCH
* @see TABLESWITCH
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class Select extends BranchInstruction implements VariableLengthInstruction, StackConsumer /* @since 6.0 */, StackProducer {
@@ -87,7 +87,7 @@ public abstract class Select extends BranchInstruction implements VariableLength
* @param defaultTarget default instruction target
*/
Select(final short opcode, final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) {
- // don't set default target before instuction is built
+ // don't set default target before instruction is built
super(opcode, null);
this.match = match;
this.targets = targets;
@@ -288,7 +288,7 @@ final int setMatchLength(final int matchLength) {
}
/**
- * Set branch target for 'i'th case
+ * Sets branch target for 'i'th case
*/
public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected?
notifyTarget(targets[i], target, this);
@@ -314,7 +314,11 @@ public String toString(final boolean verbose) {
for (int i = 0; i < match_length; i++) {
String s = "null";
if (targets[i] != null) {
- s = targets[i].getInstruction().toString();
+ if (targets[i].getInstruction() == this) {
+ s = "";
+ } else {
+ s = targets[i].getInstruction().toString();
+ }
}
buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(indices[i]).append("})");
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
index a4de20315d7..363b3237632 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
@@ -166,7 +166,7 @@ public void dump(final DataOutputStream dos) throws IOException {
dos.writeShort(idx);
break;
default:
- throw new IllegalStateException("SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType());
+ throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType());
}
}
@@ -184,7 +184,7 @@ public int getIndex() {
public int getValueInt() {
if (super.getElementValueType() != PRIMITIVE_INT) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
return c.getBytes();
@@ -192,7 +192,7 @@ public int getValueInt() {
public String getValueString() {
if (super.getElementValueType() != STRING) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx);
return c.getBytes();
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
index 40ed6ff4c38..038bbe63148 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -21,32 +21,32 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Thrown by InstructionList.remove() when one or multiple disposed instructions are still being referenced by an
- * InstructionTargeter object. I.e. the InstructionTargeter has to be notified that (one of) the InstructionHandle it is
- * referencing is being removed from the InstructionList and thus not valid anymore.
+ * Thrown by {@link InstructionList} when one or multiple disposed instructions are still being referenced by an {@link InstructionTargeter} object. I.e. the
+ * {@link InstructionTargeter} has to be notified that (one of) the {@link InstructionHandle} it is referencing is being removed from the
+ * {@link InstructionList} and thus not valid anymore.
*
*
- * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... }
- * catch. The following code illustrates how this may be done:
+ * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } catch. The following code illustrates how
+ * this may be done:
*
*
* @see InstructionHandle
* @see InstructionList
* @see InstructionTargeter
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class TargetLostException extends Exception {
@@ -54,12 +54,14 @@ public final class TargetLostException extends Exception {
@SuppressWarnings("serial") // Array component type is not Serializable
private final InstructionHandle[] targets;
- TargetLostException(final InstructionHandle[] t, final String mesg) {
- super(mesg);
- targets = t;
+ TargetLostException(final InstructionHandle[] targets, final String message) {
+ super(message);
+ this.targets = targets;
}
/**
+ * Gets the list of instructions still being targeted.
+ *
* @return list of instructions still being targeted.
*/
public InstructionHandle[] getTargets() {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
index ea20710af2e..b58645b402e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -26,12 +26,14 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;
+import com.sun.org.apache.bcel.internal.classfile.InvalidMethodSignatureException;
import com.sun.org.apache.bcel.internal.classfile.Utility;
+import jdk.xml.internal.Utils;
/**
- * Abstract super class for all possible java types, namely basic types such as int, object types like String and array
+ * Abstract super class for all possible Java types, namely basic types such as int, object types like String and array
* types, e.g. int[]
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class Type {
@@ -88,15 +90,15 @@ public static Type[] getArgumentTypes(final String signature) {
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
vec.add(getType(signature.substring(index)));
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
index += unwrap(CONSUMED_CHARS); // update position
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
final Type[] types = new Type[vec.size()];
vec.toArray(types);
@@ -110,7 +112,7 @@ static int getArgumentTypesSize(final String signature) {
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
final int coded = getTypeSize(signature.substring(index));
@@ -118,7 +120,7 @@ static int getArgumentTypesSize(final String signature) {
index += consumed(coded);
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return res;
}
@@ -154,13 +156,13 @@ public static Type getReturnType(final String signature) {
final int index = signature.lastIndexOf(')') + 1;
return getType(signature.substring(index));
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
static int getReturnTypeSize(final String signature) {
final int index = signature.lastIndexOf(')') + 1;
- return Type.size(getTypeSize(signature.substring(index)));
+ return size(getTypeSize(signature.substring(index)));
}
public static String getSignature(final java.lang.reflect.Method meth) {
@@ -175,7 +177,7 @@ public static String getSignature(final java.lang.reflect.Method meth) {
}
/**
- * Convert runtime java.lang.Class to BCEL Type object.
+ * Convert runtime {@link Class} to BCEL Type object.
*
* @param cls Java class
* @return corresponding Type object
@@ -183,7 +185,7 @@ public static String getSignature(final java.lang.reflect.Method meth) {
public static Type getType(final Class> cls) {
Objects.requireNonNull(cls, "cls");
/*
- * That's an amzingly easy case, because getName() returns the signature. That's what we would have liked anyway.
+ * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway.
*/
if (cls.isArray()) {
return getType(cls.getName());
@@ -230,7 +232,7 @@ public static Type getType(final Class> cls) {
public static Type getType(final String signature) throws StringIndexOutOfBoundsException {
final byte type = Utility.typeOfSignature(signature);
if (type <= Const.T_VOID) {
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
wrap(CONSUMED_CHARS, 1);
return BasicType.getType(type);
}
@@ -246,7 +248,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds
} while (signature.charAt(dim) == '[');
// Recurse, but just once, if the signature is ok
final Type t = getType(signature.substring(dim));
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
// consumed_chars += dim; // update counter - is replaced by
final int temp = unwrap(CONSUMED_CHARS) + dim;
wrap(CONSUMED_CHARS, temp);
@@ -254,7 +256,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds
}
/**
- * Convert runtime java.lang.Class[] to BCEL Type objects.
+ * Convert runtime {@code java.lang.Class[]} to BCEL Type objects.
*
* @param classes an array of runtime class objects
* @return array of corresponding Type objects
@@ -286,6 +288,24 @@ static int getTypeSize(final String signature) throws StringIndexOutOfBoundsExce
return encode(1, index + 1);
}
+ static String internalTypeNameToSignature(final String internalTypeName) {
+ if (Utils.isEmpty(internalTypeName) || Arrays.asList(Const.SHORT_TYPE_NAMES).contains(internalTypeName)) {
+ return internalTypeName;
+ }
+ switch (internalTypeName.charAt(0)) {
+ case '[':
+ return internalTypeName;
+ case 'L':
+ case 'T':
+ if (internalTypeName.charAt(internalTypeName.length() - 1) == ';') {
+ return internalTypeName;
+ }
+ return 'L' + internalTypeName + ';';
+ default:
+ return 'L' + internalTypeName + ';';
+ }
+ }
+
static int size(final int coded) {
return coded & 3;
}
@@ -361,7 +381,7 @@ public byte getType() {
}
/**
- * @return hashcode of Type
+ * @return hash code of Type
*/
@Override
public int hashCode() {
@@ -369,31 +389,23 @@ public int hashCode() {
}
/**
- * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link Type#INT}
- * for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise returns the given type.
+ * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link #INT}
+ * for {@link #BOOLEAN}, {@link #SHORT} or {@link #CHAR}, otherwise returns the given type.
*
* @since 6.0
*/
public Type normalizeForStackOrLocal() {
- if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) {
- return Type.INT;
+ if (this == BOOLEAN || this == BYTE || this == SHORT || this == CHAR) {
+ return INT;
}
return this;
}
- /*
- * Currently only used by the ArrayType constructor. The signature has a complicated dependency on other parameter so
- * it's tricky to do it in a call to the super ctor.
- */
- void setSignature(final String signature) {
- this.signature = signature;
- }
-
/**
* @return Type string, e.g. 'int[]'
*/
@Override
public String toString() {
- return this.equals(Type.NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false);
+ return equals(NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false);
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
index 5a22942a6a7..27b952f3996 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
@@ -22,7 +22,7 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Get the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g..
+ * Gets the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g..
*/
public interface TypedInstruction {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java
new file mode 100644
index 00000000000..63d4dc876ce
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Generic part of the Apache Byte Code Engineering Library (BCEL), classes to dynamically modify class objects
+ * and byte code instructions.
+ */
+package com.sun.org.apache.bcel.internal.generic;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java
new file mode 100644
index 00000000000..581037d7981
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Basic classes for the Apache Byte Code Engineering Library (BCEL) and constants defined by the
+ * JVM specification.
+ */
+package com.sun.org.apache.bcel.internal;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
index 2e663bfdaa1..fb32dc35e0b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
@@ -22,26 +22,27 @@
package com.sun.org.apache.bcel.internal.util;
/**
- * Used for BCEL comparison strategy
+ * Used for BCEL comparison strategy.
*
+ * @param What type we are comparing.
* @since 5.2
*/
-public interface BCELComparator {
+public interface BCELComparator {
/**
- * Compare two objects and return what THIS.equals(THAT) should return
+ * Compares two objects and return what a.equals(b) should return.
*
- * @param THIS
- * @param THAT
- * @return true if and only if THIS equals THAT
+ * @param a an object.
+ * @param b an object to be compared with {@code a} for equality.
+ * @return {@code true} if the arguments are equal to each other and {@code false} otherwise.
*/
- boolean equals(Object THIS, Object THAT);
+ boolean equals(T a, T b);
/**
- * Return hashcode for THIS.hashCode()
+ * Gets the hash code for o.hashCode()
*
- * @param THIS
- * @return hashcode for THIS.hashCode()
+ * @param o
+ * @return hash code for o.hashCode()
*/
- int hashCode(Object THIS);
+ int hashCode(T o);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
index c931fb1e422..93f22e7d0ad 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -63,9 +63,9 @@
* Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier.
*
* @see BCELifier
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
-class BCELFactory extends EmptyVisitor {
+final class BCELFactory extends EmptyVisitor {
private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + ".";
private final MethodGen methodGen;
@@ -88,7 +88,7 @@ private void createConstant(final Object value) {
if (value instanceof String) {
embed = '"' + Utility.convertString(embed) + '"';
} else if (value instanceof Character) {
- embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
+ embed = "(char) 0x" + Integer.toHexString(((Character) value).charValue());
} else if (value instanceof Float) {
final Float f = (Float) value;
if (Float.isNaN(f)) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
index 151083ea71b..0eb9bfb4ee1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,11 +30,15 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.ClassParser;
+import com.sun.org.apache.bcel.internal.classfile.Code;
import com.sun.org.apache.bcel.internal.classfile.ConstantValue;
import com.sun.org.apache.bcel.internal.classfile.ExceptionTable;
import com.sun.org.apache.bcel.internal.classfile.Field;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Method;
+import com.sun.org.apache.bcel.internal.classfile.StackMap;
+import com.sun.org.apache.bcel.internal.classfile.StackMapEntry;
+import com.sun.org.apache.bcel.internal.classfile.StackMapType;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import com.sun.org.apache.bcel.internal.generic.ArrayType;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
@@ -46,7 +50,7 @@
* This gives new users of BCEL a useful example showing how things are done with BCEL. It does not cover all features
* of BCEL, but tries to mimic hand-written code as close as possible.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor {
@@ -74,7 +78,7 @@ static JavaClass getJavaClass(final String name) throws ClassNotFoundException,
/**
* Default main method
*/
- public static void _main(final String[] argv) throws Exception {
+ public static void main(final String[] argv) throws Exception {
if (argv.length != 1) {
System.out.println("Usage: BCELifier className");
System.out.println("\tThe class must exist on the classpath");
@@ -311,6 +315,13 @@ public void visitMethod(final Method method) {
printWriter.println("\");");
}
}
+ final Code code = method.getCode();
+ if (code != null) {
+ final StackMap stackMap = code.getStackMap();
+ if (stackMap != null) {
+ stackMap.accept(this);
+ }
+ }
printWriter.println();
final BCELFactory factory = new BCELFactory(mg, printWriter);
factory.start();
@@ -319,4 +330,78 @@ public void visitMethod(final Method method) {
printWriter.println(" _cg.addMethod(method.getMethod());");
printWriter.println(" il.dispose();");
}
+
+ @Override
+ public void visitStackMap(final StackMap stackMap) {
+ super.visitStackMap(stackMap);
+ printWriter.print(" method.addCodeAttribute(");
+ printWriter.print("new StackMap(_cp.addUtf8(\"");
+ printWriter.print(stackMap.getName());
+ printWriter.print("\"), ");
+ printWriter.print(stackMap.getLength());
+ printWriter.print(", ");
+ printWriter.print("new StackMapEntry[] {");
+ final StackMapEntry[] table = stackMap.getStackMap();
+ for (int i = 0; i < table.length; i++) {
+ table[i].accept(this);
+ if (i < table.length - 1) {
+ printWriter.print(", ");
+ } else {
+ printWriter.print(" }");
+ }
+ }
+ printWriter.print(", _cp.getConstantPool())");
+ printWriter.println(");");
+ }
+
+ @Override
+ public void visitStackMapEntry(final StackMapEntry stackMapEntry) {
+ super.visitStackMapEntry(stackMapEntry);
+ printWriter.print("new StackMapEntry(");
+ printWriter.print(stackMapEntry.getFrameType());
+ printWriter.print(", ");
+ printWriter.print(stackMapEntry.getByteCodeOffset());
+ printWriter.print(", ");
+ visitStackMapTypeArray(stackMapEntry.getTypesOfLocals());
+ printWriter.print(", ");
+ visitStackMapTypeArray(stackMapEntry.getTypesOfStackItems());
+ printWriter.print(", _cp.getConstantPool())");
+ }
+
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param stackMapType object to visit
+ * @since 6.7.1
+ */
+ @Override
+ public void visitStackMapType(final StackMapType stackMapType) {
+ super.visitStackMapType(stackMapType);
+ printWriter.print("new StackMapType((byte)");
+ printWriter.print(stackMapType.getType());
+ printWriter.print(", ");
+ if (stackMapType.hasIndex()) {
+ printWriter.print("_cp.addClass(\"");
+ printWriter.print(stackMapType.getClassName());
+ printWriter.print("\")");
+ } else {
+ printWriter.print("-1");
+ }
+ printWriter.print(", _cp.getConstantPool())");
+ }
+
+ private void visitStackMapTypeArray(final StackMapType[] types) {
+ if (types == null || types.length == 0) {
+ printWriter.print("null"); // null translates to StackMapType.EMPTY_ARRAY
+ } else {
+ printWriter.print("new StackMapType[] {");
+ for (int i = 0; i < types.length; i++) {
+ types[i].accept(this);
+ if (i < types.length - 1) {
+ printWriter.print(", ");
+ } else {
+ printWriter.print(" }");
+ }
+ }
+ }
+ }
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
index f644c698b72..10d31974d47 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -53,7 +53,7 @@
* All subfiles reference each other appropriately, e.g. clicking on a method in the Method's frame will jump to the
* appropriate method in the Code frame.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class Class2HTML {
@@ -73,7 +73,7 @@ public class Class2HTML {
basicTypes.add("float");
}
- public static void _main(final String[] argv) throws IOException {
+ public static void main(final String[] argv) throws IOException {
final String[] fileName = new String[argv.length];
int files = 0;
ClassParser parser = null;
@@ -89,7 +89,7 @@ public static void _main(final String[] argv) throws IOException {
if (argv[i].equals("-d")) { // Specify target directory, default '.'
dir = argv[++i];
if (!dir.endsWith("" + sep)) {
- dir = dir + sep;
+ dir += sep;
}
final File store = new File(dir);
if (!store.isDirectory()) {
@@ -115,7 +115,7 @@ public static void _main(final String[] argv) throws IOException {
if (zipFile == null) {
parser = new ClassParser(fileName[i]); // Create parser object from file
} else {
- parser = new ClassParser(zipFile, fileName[i]); // Create parser object from zip file
+ parser = new ClassParser(zipFile, fileName[i]); // Create parser object from ZIP file
}
javaClass = parser.parse();
new Class2HTML(javaClass, dir);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
index 178ccc786b1..e95e8fbd0a0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,7 +30,7 @@
* Utility class implementing a (type-safe) set of JavaClass objects. Since JavaClass has no equals() method, the name of the class is used for comparison.
*
* @see ClassStack
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ClassSet {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
index 723fc07509b..1935d724b3b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
@@ -542,7 +542,7 @@ private void writeMethod(final Method method, final int methodNumber) throws IOE
final String str = codeToHTML(stream, methodNumber);
String anchor = "";
/*
- * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very
+ * Sets an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very
* inefficient!
*/
if (gotoSet.get(offset)) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
index 5b045bf08cc..510fe4a03a6 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -63,14 +63,13 @@
*
* @see com.sun.org.apache.bcel.internal.generic.Instruction
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class InstructionFinder {
/**
* Code patterns found may be checked using an additional user-defined constraint object whether they really match the
* needed criterion. I.e., check constraints that can not expressed with regular expressions.
- *
*/
public interface CodeConstraint {
@@ -374,7 +373,7 @@ public final Iterator search(final String pattern, final In
// }
// private static final String pattern2string( String pattern, boolean make_string ) {
-// StringBuffer buf = new StringBuffer();
+// StringBuilder buf = new StringBuilder();
// for (int i = 0; i < pattern.length(); i++) {
// char ch = pattern.charAt(i);
// if (ch >= OFFSET) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
index 8d1ddf493cd..c44e36d0a81 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,8 +25,8 @@
* Abstract definition of a class repository. Instances may be used to load classes from different sources and may be
* used in the Repository.setRepository method.
*
- * @see org.apache.bcel.Repository
- * @LastModified: Feb 2023
+ * @see com.sun.org.apache.bcel.internal.Repository
+ * @LastModified: Sept 2025
*/
public interface Repository {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java
new file mode 100644
index 00000000000..2bd92f155bc
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Utility classes for the Apache Byte Code Engineering Library (BCEL), namely:
+ *
+ *
Collection classes for JavaClass objects
+ *
A converter for class files to HTML
+ *
A tool to find instructions patterns via regular expressions
+ *
A class to find classes as defined in the CLASSPATH
+ *
A class loader that allows to create classes at run time
+ *
+ */
+package com.sun.org.apache.bcel.internal.util;
diff --git a/src/java.xml/share/classes/jdk/xml/internal/Utils.java b/src/java.xml/share/classes/jdk/xml/internal/Utils.java
index f55ab95a58f..96d9b1b9521 100644
--- a/src/java.xml/share/classes/jdk/xml/internal/Utils.java
+++ b/src/java.xml/share/classes/jdk/xml/internal/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -25,8 +25,11 @@
package jdk.xml.internal;
+import java.lang.reflect.Array;
import java.util.Arrays;
+import java.util.Objects;
import java.util.function.Supplier;
+import java.util.stream.Stream;
/**
* General utility. Use JdkXmlUtils for XML processing related functions.
@@ -76,4 +79,59 @@ public static Class>[] arraysAppend(final Class>[] original, final Class>.
System.arraycopy(items, 0, result, original.length, items.length);
return result;
}
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param array the specified array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static byte[] createEmptyArrayIfNull(byte[] array) {
+ return (array != null) ? array : new byte[0];
+ }
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param array the specified array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static int[] createEmptyArrayIfNull(int[] array) {
+ return (array != null) ? array : new int[0];
+ }
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param the class type
+ * @param array the specified array
+ * @param type the type of the array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static T[] createEmptyArrayIfNull(final T[] array, final Class type) {
+ Objects.requireNonNull(type, "The type argument should not be null.");
+
+ return (array != null) ? array : type.cast(Array.newInstance(type.getComponentType(), 0));
+ }
+
+ /**
+ * Returns the new stream created by {@code Stream.of(values)} or an empty
+ * sequential stream created by {@code Stream.empty()} if values is null.
+ *
+ * @param the type of stream elements
+ * @param values the elements of the new stream
+ * @return the new stream created by {@code Stream.of(values)} or an empty
+ * sequential stream created by {@code Stream.empty()} if values is null.
+ */
+ @SafeVarargs
+ @SuppressWarnings("varargs") // Creating a stream from an array is safe
+ public static Stream streamOfIfNonNull(final T... values) {
+ return values == null ? Stream.empty() : Stream.of(values);
+ }
+
+ /**
+ * Checks if a CharSequence is empty ("") or null.
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is empty or null
+ */
+ public static boolean isEmpty(final CharSequence cs) {
+ return cs == null || cs.length() == 0;
+ }
}
diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md
index 2c673d6b1af..b64fc3640d4 100644
--- a/src/java.xml/share/legal/bcel.md
+++ b/src/java.xml/share/legal/bcel.md
@@ -1,4 +1,4 @@
-## Apache Commons Byte Code Engineering Library (BCEL) Version 6.7.0
+## Apache Commons Byte Code Engineering Library (BCEL) Version 6.10.0
### Apache Commons BCEL Notice
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
index 725c7f8063b..e916466998e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -756,6 +756,11 @@ public CondItem genCond(JCTree _tree, boolean markBranches) {
}
CondItem result = genCond(tree.expr, markBranches);
code.endScopes(limit);
+ //make sure variables defined in the let expression are not included
+ //in the defined variables for jumps that go outside of this let
+ //expression:
+ undefineVariablesInChain(result.falseJumps, limit);
+ undefineVariablesInChain(result.trueJumps, limit);
return result;
} else {
CondItem result = genExpr(_tree, syms.booleanType).mkCond();
@@ -763,6 +768,13 @@ public CondItem genCond(JCTree _tree, boolean markBranches) {
return result;
}
}
+ //where:
+ private void undefineVariablesInChain(Chain toClear, int limit) {
+ while (toClear != null) {
+ toClear.state.defined.excludeFrom(limit);
+ toClear = toClear.next;
+ }
+ }
public Code getCode() {
return code;
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java
new file mode 100644
index 00000000000..183a71ee806
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/RSACipherAdaptor.java
@@ -0,0 +1,155 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.pkcs11;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureSpi;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.ProviderException;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import sun.security.pkcs11.wrapper.PKCS11Exception;
+
+/**
+ * NONEwithRSA Signature implementation using the RSA/ECB/PKCS1Padding Cipher
+ * implementation from SunPKCS11.
+ */
+public final class RSACipherAdaptor extends SignatureSpi {
+
+ private final P11RSACipher c;
+ private ByteArrayOutputStream verifyBuf;
+
+ public RSACipherAdaptor(Token token, long mechanism) {
+ try {
+ c = new P11RSACipher(token, "", mechanism);
+ c.engineSetPadding("pkcs1padding");
+ } catch (PKCS11Exception | NoSuchPaddingException e) {
+ // should not happen, but wrap and re-throw if it were to happen
+ throw new ProviderException(e);
+ }
+ }
+
+ @Override
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.DECRYPT_MODE, publicKey, null);
+ if (verifyBuf == null) {
+ verifyBuf = new ByteArrayOutputStream(128);
+ } else {
+ verifyBuf.reset();
+ }
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.ENCRYPT_MODE, privateKey, null);
+ verifyBuf = null;
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException {
+ c.engineInit(Cipher.ENCRYPT_MODE, privateKey, random);
+ verifyBuf = null;
+ }
+
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ engineUpdate(new byte[] {b}, 0, 1);
+ }
+
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ if (verifyBuf != null) {
+ verifyBuf.write(b, off, len);
+ } else {
+ byte[] out = c.engineUpdate(b, off, len);
+ if ((out != null) && (out.length != 0)) {
+ throw new SignatureException
+ ("Cipher unexpectedly returned data");
+ }
+ }
+ }
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ try {
+ return c.engineDoFinal(null, 0, 0);
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ try {
+ byte[] out = c.engineDoFinal(sigBytes, 0, sigBytes.length);
+ byte[] data = verifyBuf.toByteArray();
+ verifyBuf.reset();
+ return MessageDigest.isEqual(out, data);
+ } catch (BadPaddingException e) {
+ // e.g. wrong public key used
+ // return false rather than throwing exception
+ return false;
+ } catch (IllegalBlockSizeException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ @Override
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ if (params != null) {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index eb0569ec0d4..00d8559e696 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -974,6 +974,8 @@ private static void register(Descriptor d) {
d(SIG, "SHA3-512withECDSAinP1363Format", P11Signature,
m(CKM_ECDSA_SHA3_512, CKM_ECDSA));
+ d(SIG, "NONEwithRSA", "sun.security.pkcs11.RSACipherAdaptor",
+ m(CKM_RSA_PKCS));
dA(SIG, "MD2withRSA", P11Signature,
m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
dA(SIG, "MD5withRSA", P11Signature,
@@ -1425,6 +1427,8 @@ public Object newInstance0(Object param) throws
} else if (type == SIG) {
if (algorithm.contains("RSASSA-PSS")) {
return new P11PSSSignature(token, algorithm, mechanism);
+ } else if (algorithm.equals("NONEwithRSA")) {
+ return new RSACipherAdaptor(token, mechanism);
} else {
return new P11Signature(token, algorithm, mechanism);
}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
index 20c5fabf8bc..f93728103e3 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
@@ -180,6 +180,11 @@ public ImmutableOopMapSet getOopMaps() {
public boolean isUpcallStub() { return getKind() == UpcallKind; }
+ public boolean isContinuationStub() {
+ // NOTE: In newer versions this is renamed to "continuation stubs" by JDK-8360707.
+ return getName().equals("StubRoutines (continuationstubs)");
+ }
+
public boolean isJavaMethod() { return false; }
public boolean isNativeMethod() { return false; }
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java
new file mode 100644
index 00000000000..73152bdee84
--- /dev/null
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, NTT DATA.
+ * 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 sun.jvm.hotspot.runtime;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+
+public class ContinuationEntry extends VMObject {
+ private static long size;
+ private static Address returnPC;
+
+ static {
+ VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
+ }
+
+ private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+ Type type = db.lookupType("ContinuationEntry");
+ size = type.getSize();
+ returnPC = type.getAddressField("_return_pc").getValue();
+ }
+
+ public ContinuationEntry(Address addr) {
+ super(addr);
+ }
+
+ public Address getEntryPC() {
+ return returnPC;
+ }
+
+ public Address getEntrySP(){
+ return this.getAddress();
+ }
+
+ public Address getEntryFP(){
+ return this.getAddress().addOffsetTo(size);
+ }
+
+}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
index d92f464f0d2..826b5cecfd5 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
@@ -47,6 +47,7 @@ public class JavaThread extends Thread {
private static AddressField stackBaseField;
private static CIntegerField stackSizeField;
private static CIntegerField terminatedField;
+ private static AddressField contEntryField;
private static AddressField activeHandlesField;
private static CIntegerField monitorOwnerIDField;
private static long oopPtrSize;
@@ -95,6 +96,7 @@ private static synchronized void initialize(TypeDataBase db) {
stackBaseField = type.getAddressField("_stack_base");
stackSizeField = type.getCIntegerField("_stack_size");
terminatedField = type.getCIntegerField("_terminated");
+ contEntryField = type.getAddressField("_cont_entry");
activeHandlesField = type.getAddressField("_active_handles");
monitorOwnerIDField = type.getCIntegerField("_monitor_owner_id");
@@ -340,6 +342,10 @@ public int getTerminated() {
return (int) terminatedField.getValue(addr);
}
+ public ContinuationEntry getContEntry() {
+ return VMObjectFactory.newObject(ContinuationEntry.class, contEntryField.getValue(addr));
+ }
+
/** Gets the Java-side thread object for this JavaThread */
public Oop getThreadObj() {
Oop obj = null;
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
index dca5f2efa3b..3746f676c11 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java
@@ -292,7 +292,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}
if (cb != null) {
- return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+ if (cb.isUpcallStub()) {
+ return senderForUpcallStub(map, (UpcallStub)cb);
+ } else if (cb.isContinuationStub()) {
+ return senderForContinuationStub(map, cb);
+ } else {
+ return senderForCompiledFrame(map, cb);
+ }
}
// Must be native-compiled frame, i.e. the marshaling code for native
@@ -396,6 +402,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(fp, savedFPAddr);
}
+ private Frame senderForContinuationStub(AARCH64RegisterMap map, CodeBlob cb) {
+ var contEntry = map.getThread().getContEntry();
+
+ Address senderSP = contEntry.getEntrySP();
+ Address senderPC = contEntry.getEntryPC();
+ Address senderFP = contEntry.getEntryFP();
+
+ return new AARCH64Frame(senderSP, senderFP, senderPC);
+ }
+
private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
index a47a632c286..c3cefc861e9 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
@@ -279,7 +279,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}
if (cb != null) {
- return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+ if (cb.isUpcallStub()) {
+ return senderForUpcallStub(map, (UpcallStub)cb);
+ } else if (cb.isContinuationStub()) {
+ return senderForContinuationStub(map, cb);
+ } else {
+ return senderForCompiledFrame(map, cb);
+ }
}
// Must be native-compiled frame, i.e. the marshaling code for native
@@ -358,6 +364,15 @@ private Frame senderForInterpreterFrame(PPC64RegisterMap map) {
return new PPC64Frame(sp, unextendedSP, getLink(), getSenderPC());
}
+ private Frame senderForContinuationStub(PPC64RegisterMap map, CodeBlob cb) {
+ var contEntry = map.getThread().getContEntry();
+
+ Address sp = contEntry.getEntrySP();
+ Address pc = contEntry.getEntryPC();
+ Address fp = contEntry.getEntryFP();
+
+ return new PPC64Frame(sp, fp, pc);
+ }
private Frame senderForCompiledFrame(PPC64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
index 948a3008016..f9b09a94dd4 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
@@ -284,7 +284,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}
if (cb != null) {
- return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+ if (cb.isUpcallStub()) {
+ return senderForUpcallStub(map, (UpcallStub)cb);
+ } else if (cb.isContinuationStub()) {
+ return senderForContinuationStub(map, cb);
+ } else {
+ return senderForCompiledFrame(map, cb);
+ }
}
// Must be native-compiled frame, i.e. the marshaling code for native
@@ -388,6 +394,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(fp, savedFPAddr);
}
+ private Frame senderForContinuationStub(RISCV64RegisterMap map, CodeBlob cb) {
+ var contEntry = map.getThread().getContEntry();
+
+ Address senderSP = contEntry.getEntrySP();
+ Address senderPC = contEntry.getEntryPC();
+ Address senderFP = contEntry.getEntryFP();
+
+ return new RISCV64Frame(senderSP, senderFP, senderPC);
+ }
+
private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
index 169ecea1565..8ac68e6c7ca 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
@@ -289,7 +289,13 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) {
}
if (cb != null) {
- return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
+ if (cb.isUpcallStub()) {
+ return senderForUpcallStub(map, (UpcallStub)cb);
+ } else if (cb.isContinuationStub()) {
+ return senderForContinuationStub(map, cb);
+ } else {
+ return senderForCompiledFrame(map, cb);
+ }
}
// Must be native-compiled frame, i.e. the marshaling code for native
@@ -393,6 +399,16 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
map.setLocation(rbp, savedFPAddr);
}
+ private Frame senderForContinuationStub(X86RegisterMap map, CodeBlob cb) {
+ var contEntry = map.getThread().getContEntry();
+
+ Address senderSP = contEntry.getEntrySP();
+ Address senderPC = contEntry.getEntryPC();
+ Address senderFP = contEntry.getEntryFP();
+
+ return new X86Frame(senderSP, senderFP, senderPC);
+ }
+
private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
index 365f6d1e68a..4e4751b264e 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
@@ -50,7 +50,7 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
*/
@Override
public JdkConsole console(boolean isTTY, Charset inCharset, Charset outCharset) {
- return new LazyDelegatingJdkConsoleImpl(inCharset, outCharset);
+ return isTTY ? new LazyDelegatingJdkConsoleImpl(inCharset, outCharset) : null;
}
private static class LazyDelegatingJdkConsoleImpl implements JdkConsole {
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
index 0cb56354498..b25f7a09256 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
@@ -654,6 +654,8 @@ native int installCode0(long compiledCodeBuffer,
long failedSpeculationsAddress,
byte[] speculations);
+ native String getInvalidationReasonDescription(int invalidationReason);
+
/**
* Gets flags specifying optional parts of code info. Only if a flag is set, will the
* corresponding code info being included in the {@linkplain HotSpotCompiledCodeStream
@@ -842,7 +844,7 @@ void reprofile(HotSpotResolvedJavaMethodImpl method) {
* {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and if
* {@code deoptimize == true} any current activations of the {@code nmethod} are deoptimized.
*/
- native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize);
+ native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason);
/**
* Collects the current values of all JVMCI benchmark counters, summed up over all threads.
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
index a0130d1bda9..9545c9aa9ec 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
@@ -154,16 +154,20 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile
return logOrDump(resultInstalledCode, compiledCode);
}
- @Override
- public void invalidateInstalledCode(InstalledCode installedCode) {
+ public void invalidateInstalledCode(InstalledCode installedCode, int invalidationReason) {
if (installedCode instanceof HotSpotNmethod) {
HotSpotNmethod nmethod = (HotSpotNmethod) installedCode;
- nmethod.invalidate(true);
+ nmethod.invalidate(true, invalidationReason);
} else {
throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
}
}
+ @Override
+ public void invalidateInstalledCode(InstalledCode installedCode) {
+ invalidateInstalledCode(installedCode, jvmciInvalidationReason());
+ }
+
@Override
public TargetDescription getTarget() {
return target;
@@ -201,4 +205,8 @@ public int interpreterFrameSize(BytecodeFrame pos) {
public void resetCompilationStatistics() {
runtime.getCompilerToVM().resetCompilationStatistics();
}
+
+ private static int jvmciInvalidationReason() {
+ return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class);
+ }
}
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
index 9ed03f9749e..5c7089da6cb 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java
@@ -27,6 +27,7 @@
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -76,12 +77,19 @@ boolean inOopsTable() {
*/
private final long compileIdSnapshot;
+ /**
+ * Identify the reason that caused this nmethod to be invalidated.
+ * A value of -1 means that the nmethod was not invalidated.
+ */
+ private int invalidationReason;
+
HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
super(name);
this.method = method;
this.isDefault = isDefault;
boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
this.compileIdSnapshot = inOopsTable ? 0L : compileId;
+ this.invalidationReason = -1;
assert inOopsTable || compileId != 0L : this;
}
@@ -122,9 +130,19 @@ public ResolvedJavaMethod getMethod() {
return method;
}
+ /**
+ * Invalidate this nmethod using the reason specified in {@code invalidationReason} and
+ * optionally deoptimize the method if {@code deoptimize} is set.
+ * @param deoptimize whether or not to deoptimize the method.
+ * @param invalidationReason invalidation reason code.
+ */
+ public void invalidate(boolean deoptimize, int invalidationReason) {
+ compilerToVM().invalidateHotSpotNmethod(this, deoptimize, invalidationReason);
+ }
+
@Override
public void invalidate(boolean deoptimize) {
- compilerToVM().invalidateHotSpotNmethod(this, deoptimize);
+ invalidate(deoptimize, jvmciInvalidationReason());
}
@Override
@@ -188,4 +206,22 @@ public Object executeVarargs(Object... args) throws InvalidInstalledCodeExceptio
public long getStart() {
return isValid() ? super.getStart() : 0;
}
+
+ /**
+ * @return an integer representing the reason why this nmethod was invalidated.
+ */
+ public int getInvalidationReason() {
+ return invalidationReason;
+ }
+
+ /**
+ * @return a String describing the reason why this nmethod was invalidated.
+ */
+ public String getInvalidationReasonDescription() {
+ return compilerToVM().getInvalidationReasonDescription(this.getInvalidationReason());
+ }
+
+ private static int jvmciInvalidationReason() {
+ return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class);
+ }
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
index 778e2625f32..433a641530d 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java
@@ -108,6 +108,7 @@ private Content createModuleSelector() {
var select = HtmlTree.of(HtmlTag.SELECT)
.setId(HtmlId.of("search-modules"))
+ .put(HtmlAttr.ARIA_LABEL, resources.getText("doclet.selectModule"))
.add(HtmlTree.of(HtmlTag.OPTION)
.put(HtmlAttr.VALUE, "")
.add(contents.getContent("doclet.search.all_modules")));
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
index 9b111cb5edf..d469ef66534 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
@@ -783,3 +783,6 @@ doclet.NoFrames_specified=\
doclet.footer_specified=\
The -footer option is no longer supported and will be ignored.\n\
It may be removed in a future release.
+
+doclet.selectModule=\
+ Select the module to search in.
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
index 2d81a2914e6..f53a71a6999 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/html/HtmlTree.java
@@ -586,8 +586,7 @@ public static HtmlTree EM(String body) {
* @return the element
*/
public static HtmlTree FOOTER() {
- return new HtmlTree(HtmlTag.FOOTER)
- .setRole(HtmlAttr.Role.CONTENTINFO);
+ return new HtmlTree(HtmlTag.FOOTER);
}
/**
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
index 40876fae4e1..9b988139d44 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
@@ -49,6 +49,7 @@ public final class PlatformEventType extends Type {
private final boolean isJDK;
private final boolean isMethodSampling;
private final boolean isCPUTimeMethodSampling;
+ private final boolean isBackToBackSensitive;
private final List settings = new ArrayList<>(5);
private final boolean dynamicSettings;
private final int stackTraceOffset;
@@ -82,10 +83,25 @@ public final class PlatformEventType extends Type {
this.isJVM = Type.isDefinedByJVM(id);
this.isMethodSampling = determineMethodSampling();
this.isCPUTimeMethodSampling = isJVM && name.equals(Type.EVENT_NAME_PREFIX + "CPUTimeSample");
+ this.isBackToBackSensitive = determineBackToBackSensitive();
this.isJDK = isJDK;
this.stackTraceOffset = determineStackTraceOffset();
}
+ private boolean determineBackToBackSensitive() {
+ if (getName().equals(Type.EVENT_NAME_PREFIX + "ThreadDump")) {
+ return true;
+ }
+ if (getName().equals(Type.EVENT_NAME_PREFIX + "ClassLoaderStatistics")) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isBackToBackSensitive() {
+ return isBackToBackSensitive;
+ }
+
private boolean isExceptionEvent() {
switch (getName()) {
case Type.EVENT_NAME_PREFIX + "JavaErrorThrow" :
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
index 2184d85cf34..cf46c05b804 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
@@ -263,7 +263,7 @@ synchronized long start(PlatformRecording recording) {
if (toDisk) {
PeriodicEvents.setFlushInterval(streamInterval);
}
- PeriodicEvents.doChunkBegin();
+ PeriodicEvents.doChunkBegin(true);
Duration duration = recording.getDuration();
if (duration != null) {
recording.setStopTime(startTime.plus(duration));
@@ -335,7 +335,7 @@ synchronized void stop(PlatformRecording recording) {
finishChunk(currentChunk, stopTime, null);
}
currentChunk = newChunk;
- PeriodicEvents.doChunkBegin();
+ PeriodicEvents.doChunkBegin(false);
}
if (toDisk) {
@@ -390,7 +390,7 @@ synchronized void rotateDisk() {
finishChunk(currentChunk, timestamp, null);
}
currentChunk = newChunk;
- PeriodicEvents.doChunkBegin();
+ PeriodicEvents.doChunkBegin(false);
}
private List getRunningRecordings() {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
index 46dab564ac0..c8db9aef169 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java
@@ -257,6 +257,11 @@ private void processOrdered(Dispatcher c) throws IOException {
}
for (int i = 0; i < index; i++) {
c.dispatch(sortedCache[i]);
+ sortedCache[i] = null;
+ }
+ // Shrink array
+ if (index > 100_000 && 4 * index < sortedCache.length) {
+ sortedCache = new RecordedEvent[2 * index];
}
onFlush();
return;
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
index 56d9fe01d79..82712fcbedc 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java
@@ -127,6 +127,10 @@ private void processOrdered(Dispatcher c) throws IOException {
cacheSorted[index++] = event;
}
dispatchOrdered(c, index);
+ if (index > 100_000 && 4 * index < cacheSorted.length) {
+ cacheSorted = new RecordedEvent[2 * index];
+ }
+ onFlush();
index = 0;
}
}
@@ -136,8 +140,8 @@ private void dispatchOrdered(Dispatcher c, int index) {
Arrays.sort(cacheSorted, 0, index, EVENT_COMPARATOR);
for (int i = 0; i < index; i++) {
c.dispatch(cacheSorted[i]);
+ cacheSorted[i] = null;
}
- onFlush();
}
private void processUnordered(Dispatcher c) throws IOException {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
index 8cbf6334e64..92033dcce70 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
@@ -69,12 +69,14 @@ public static boolean removeEvent(Runnable runnable) {
return taskRepository.removeTask(runnable);
}
- public static void doChunkBegin() {
+ public static void doChunkBegin(boolean startRecording) {
long timestamp = JVM.counterTime();
for (EventTask task : taskRepository.getTasks()) {
var eventType = task.getEventType();
if (eventType.isEnabled() && eventType.isBeginChunk()) {
- task.run(timestamp, PeriodicType.BEGIN_CHUNK);
+ if (!eventType.isBackToBackSensitive() || startRecording) {
+ task.run(timestamp, PeriodicType.BEGIN_CHUNK);
+ }
}
}
}
diff --git a/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c b/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c
index 228c5eb5c14..ec738c6c1ce 100644
--- a/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c
+++ b/src/jdk.management/aix/native/libmanagement_ext/UnixOperatingSystem.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2020 SAP SE. All rights reserved.
+ * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,20 +28,111 @@
/* Implement and update https://bugs.openjdk.org/browse/JDK-8030957 */
#include
+#include
+#include
+#include
+#include
#include "com_sun_management_internal_OperatingSystemImpl.h"
+static struct perfMetrics{
+ unsigned long long timebase;
+ perfstat_process_t stats;
+ perfstat_cpu_total_t cpu_total;
+} counters;
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+int perfInit() {
+ static int initialized = 0;
+ if (!initialized) {
+
+ perfstat_id_t id;
+ counters.stats = (perfstat_process_t){0};
+ counters.timebase = 0;
+ int rc = perfstat_cpu_total(NULL, &counters.cpu_total, sizeof(perfstat_cpu_total_t), 1);
+ if (rc < 0) {
+ return -1;
+ }
+ rc = perfstat_process(&id, &counters.stats, sizeof(perfstat_process_t), 1);
+ if (rc < 0) {
+ return -1;
+ }
+ counters.timebase = counters.stats.last_timebase;
+ initialized = 1;
+ }
+ return initialized ? 0 : -1;
+}
+
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
- return -1.0;
+ double load = -1.0;
+ pthread_mutex_lock(&lock);
+ if (perfInit() == 0) {
+ int ret;
+ perfstat_cpu_total_t cpu_total;
+ ret = perfstat_cpu_total(NULL, &cpu_total, sizeof(perfstat_cpu_total_t), 1);
+ if (ret < 0) {
+ return -1.0;
+ }
+ long long user_diff = cpu_total.user - counters.cpu_total.user;
+ long long sys_diff = cpu_total.sys - counters.cpu_total.sys;
+ long long idle_diff = cpu_total.idle - counters.cpu_total.idle;
+ long long wait_diff = cpu_total.wait - counters.cpu_total.wait;
+ long long total = user_diff + sys_diff + idle_diff + wait_diff;
+ if (total < (user_diff + sys_diff)) {
+ total = user_diff + sys_diff;
+ }
+ if (total == 0) {
+ load = 0.0;
+ } else {
+ load = (double)(user_diff + sys_diff) / total;
+ load = MAX(load, 0.0);
+ load = MIN(load, 1.0);
+ }
+ counters.cpu_total = cpu_total;
+ }
+ pthread_mutex_unlock(&lock);
+ return load;
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
(JNIEnv *env, jobject dummy)
{
- return -1.0;
+ perfstat_process_t curr_stats;
+ perfstat_id_t id;
+ unsigned long long curr_timebase, timebase_diff;
+ double user_diff, sys_diff, delta_time;
+ double cpu_load = -1.0;
+ pthread_mutex_lock(&lock);
+ if (perfInit() == 0) {
+ int ret;
+ ret = perfstat_process(&id, &curr_stats, sizeof(perfstat_process_t), 1);
+ if (ret < 0) {
+ return -1.0;
+ }
+ curr_timebase = curr_stats.last_timebase;
+ timebase_diff = curr_timebase - counters.timebase;
+ if ((long long)timebase_diff < 0 || XINTFRAC == 0) {
+ return -1.0;
+ }
+ delta_time = HTIC2NANOSEC(timebase_diff) / 1000000000.0;
+ user_diff = (double)(curr_stats.ucpu_time - counters.stats.ucpu_time);
+ sys_diff = (double)(curr_stats.scpu_time - counters.stats.scpu_time);
+ counters.stats = curr_stats;
+ counters.timebase = curr_timebase;
+ if (delta_time == 0) {
+ cpu_load = 0.0;
+ } else {
+ cpu_load = (user_diff + sys_diff) / delta_time;
+ cpu_load = MAX(cpu_load, 0.0);
+ cpu_load = MIN(cpu_load, 1.0);
+ }
+ }
+ pthread_mutex_unlock(&lock);
+ return (jdouble)cpu_load;
}
JNIEXPORT jdouble JNICALL
diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp
new file mode 100644
index 00000000000..3dbb7c62122
--- /dev/null
+++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahMarkBitMap.cpp
@@ -0,0 +1,571 @@
+/*
+ * 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.
+ */
+
+
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahMarkBitMap.hpp"
+#include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp"
+
+BEGIN_ALLOW_FORBIDDEN_FUNCTIONS
+#include
+END_ALLOW_FORBIDDEN_FUNCTIONS
+
+#include "memory/memRegion.hpp"
+#include "unittest.hpp"
+
+#include "utilities/ostream.hpp"
+#include "utilities/vmassert_reinstall.hpp"
+#include "utilities/vmassert_uninstall.hpp"
+
+// These tests will all be skipped (unless Shenandoah becomes the default
+// collector). To execute these tests, you must enable Shenandoah, which
+// is done with:
+//
+// % make exploded-test TEST="gtest:ShenandoahOld*" CONF=release TEST_OPTS="JAVA_OPTIONS=-XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational"
+//
+// Please note that these 'unit' tests are really integration tests and rely
+// on the JVM being initialized. These tests manipulate the state of the
+// collector in ways that are not compatible with a normal collection run.
+// If these tests take longer than the minimum time between gc intervals -
+// or, more likely, if you have them paused in a debugger longer than this
+// interval - you can expect trouble. These tests will also not run in a build
+// with asserts enabled because they use APIs that expect to run on a safepoint.
+
+#ifdef ASSERT
+#define SKIP_IF_NOT_SHENANDOAH() \
+ std::cout << "skipped (debug build)\n"; \
+ return;
+#else
+#define SKIP_IF_NOT_SHENANDOAH() \
+ if (!UseShenandoahGC) { \
+ std::cout << "skipped\n"; \
+ return; \
+ }
+#endif
+
+static bool _success;
+static size_t _assertion_failures;
+
+#define MarkBitMapAssertEqual(a, b) EXPECT_EQ((a), (b)); if ((a) != (b)) { _assertion_failures++; }
+#define MarkBitMapAssertTrue(a) EXPECT_TRUE((a)); if ((a) == 0) { _assertion_failures++; }
+
+
+class ShenandoahMarkBitMapTest: public ::testing::Test {
+protected:
+
+ static void verify_bitmap_is_empty(HeapWord *start, size_t words_in_heap, ShenandoahMarkBitMap* mbm) {
+ MarkBitMapAssertTrue(mbm->is_bitmap_clear_range(start, start + words_in_heap));
+ while (words_in_heap-- > 0) {
+ MarkBitMapAssertTrue(!mbm->is_marked(start));
+ MarkBitMapAssertTrue(!mbm->is_marked_weak(start));
+ MarkBitMapAssertTrue(!mbm->is_marked_strong(start));
+ start++;
+ }
+ }
+
+ static void verify_bitmap_is_weakly_marked(ShenandoahMarkBitMap* mbm,
+ HeapWord* weakly_marked_addresses[], size_t weakly_marked_objects) {
+ for (size_t i = 0; i < weakly_marked_objects; i++) {
+ HeapWord* obj_addr = weakly_marked_addresses[i];
+ MarkBitMapAssertTrue(mbm->is_marked(obj_addr));
+ MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr));
+ }
+ }
+
+ static void verify_bitmap_is_strongly_marked(ShenandoahMarkBitMap* mbm,
+ HeapWord* strongly_marked_addresses[], size_t strongly_marked_objects) {
+ for (size_t i = 0; i < strongly_marked_objects; i++) {
+ HeapWord* obj_addr = strongly_marked_addresses[i];
+ MarkBitMapAssertTrue(mbm->is_marked(obj_addr));
+ MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr));
+ }
+ }
+
+ static void verify_bitmap_all(ShenandoahMarkBitMap* mbm, HeapWord* all_marked_addresses[],
+ bool is_weakly_marked_object[], bool is_strongly_marked_object[], size_t all_marked_objects,
+ HeapWord* heap_memory, HeapWord* end_of_heap_memory) {
+ HeapWord* last_marked_addr = &heap_memory[-1];
+ for (size_t i = 0; i < all_marked_objects; i++) {
+ HeapWord* obj_addr = all_marked_addresses[i];
+ if (is_strongly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked(obj_addr));
+ MarkBitMapAssertTrue(mbm->is_marked_strong(obj_addr));
+ }
+ if (is_weakly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked(obj_addr));
+ MarkBitMapAssertTrue(mbm->is_marked_weak(obj_addr));
+ }
+ while (++last_marked_addr < obj_addr) {
+ MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr));
+ MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr));
+ MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr));
+ }
+ last_marked_addr = obj_addr;
+ }
+ while (++last_marked_addr < end_of_heap_memory) {
+ MarkBitMapAssertTrue(!mbm->is_marked(last_marked_addr));
+ MarkBitMapAssertTrue(!mbm->is_marked_strong(last_marked_addr));
+ MarkBitMapAssertTrue(!mbm->is_marked_weak(last_marked_addr));
+ }
+
+ HeapWord* next_marked = (HeapWord*) &heap_memory[0] - 1;
+ for (size_t i = 0; i < all_marked_objects; i++) {
+ next_marked = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory);
+ MarkBitMapAssertTrue(mbm->is_marked(next_marked));
+ MarkBitMapAssertEqual(next_marked, all_marked_addresses[i]);
+ if (is_strongly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked_strong(next_marked));
+ }
+ if (is_weakly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked_weak(next_marked));
+ }
+ }
+ // We expect no more marked addresses to be found. Should return limit.
+ HeapWord* sentinel = mbm->get_next_marked_addr(next_marked + 1, end_of_heap_memory);
+ MarkBitMapAssertEqual(sentinel, end_of_heap_memory);
+
+ HeapWord* prev_marked = end_of_heap_memory + 1;
+ for (int i = (int) all_marked_objects - 1; i >= 0; i--) {
+ prev_marked = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1);
+ MarkBitMapAssertEqual(prev_marked, all_marked_addresses[i]);
+ MarkBitMapAssertTrue(mbm->is_marked(prev_marked));
+ if (is_strongly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked_strong(prev_marked));
+ }
+ if (is_weakly_marked_object[i]) {
+ MarkBitMapAssertTrue(mbm->is_marked_weak(prev_marked));
+ }
+ }
+ // We expect no more marked addresses to be found. should return prev_marked.
+ sentinel = mbm->get_prev_marked_addr(&heap_memory[0], prev_marked - 1);
+ MarkBitMapAssertEqual(sentinel, prev_marked);
+ }
+
+public:
+
+ static bool run_test() {
+ ShenandoahHeap* heap = ShenandoahHeap::heap();
+ size_t heap_size = heap->max_capacity();
+ size_t heap_size_words = heap_size / HeapWordSize;
+ HeapWord* my_heap_memory = heap->base();
+ HeapWord* end_of_my_heap = my_heap_memory + heap_size_words;
+ MemRegion heap_descriptor(my_heap_memory, heap_size_words);
+
+ _success = false;
+ _assertion_failures = 0;
+
+ size_t bitmap_page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+ size_t bitmap_size_orig = ShenandoahMarkBitMap::compute_size(heap_size);
+ size_t bitmap_size = align_up(bitmap_size_orig, bitmap_page_size);
+ size_t bitmap_word_size = (bitmap_size + HeapWordSize - 1) / HeapWordSize;
+
+ HeapWord* my_bitmap_memory = NEW_C_HEAP_ARRAY(HeapWord, bitmap_word_size, mtGC);
+
+ MarkBitMapAssertTrue(my_bitmap_memory != nullptr);
+ if (my_bitmap_memory == nullptr) {
+ std::cout <<"Cannot run test because failed to allocate bitmap memory\n" << std::flush;
+ return false;
+ }
+ MemRegion bitmap_descriptor(my_bitmap_memory, bitmap_size / HeapWordSize);
+ ShenandoahMarkBitMap mbm(heap_descriptor, bitmap_descriptor);
+
+ mbm.clear_range_large(heap_descriptor);
+ verify_bitmap_is_empty((HeapWord*) my_heap_memory, heap_size_words, &mbm);
+
+ HeapWord* weakly_marked_addresses[] = {
+ (HeapWord*) &my_heap_memory[13],
+ (HeapWord*) &my_heap_memory[14],
+ (HeapWord*) &my_heap_memory[15],
+ (HeapWord*) &my_heap_memory[16],
+ (HeapWord*) &my_heap_memory[176],
+ (HeapWord*) &my_heap_memory[240],
+ (HeapWord*) &my_heap_memory[480],
+ (HeapWord*) &my_heap_memory[1360],
+ (HeapWord*) &my_heap_memory[1488],
+ (HeapWord*) &my_heap_memory[2416],
+ (HeapWord*) &my_heap_memory[5968],
+ (HeapWord*) &my_heap_memory[8191],
+ (HeapWord*) &my_heap_memory[8192],
+ (HeapWord*) &my_heap_memory[8193]
+ };
+ size_t weakly_marked_objects = sizeof(weakly_marked_addresses) / sizeof(HeapWord*);
+ for (size_t i = 0; i < weakly_marked_objects; i++) {
+ mbm.mark_weak(weakly_marked_addresses[i]);
+ }
+ HeapWord* next_marked = (HeapWord*) &my_heap_memory[0] - 1;
+ for (size_t i = 0; i < weakly_marked_objects; i++) {
+ next_marked = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap);
+ MarkBitMapAssertEqual(next_marked, weakly_marked_addresses[i]);
+ MarkBitMapAssertTrue(mbm.is_marked(next_marked));
+ MarkBitMapAssertTrue(mbm.is_marked_weak(next_marked));
+ MarkBitMapAssertTrue(!mbm.is_marked_strong(next_marked));
+ }
+ // We expect no more marked addresses to be found. Should return limit.
+ HeapWord* sentinel = mbm.get_next_marked_addr(next_marked + 1, end_of_my_heap);
+ HeapWord* heap_limit = end_of_my_heap;
+ MarkBitMapAssertEqual(sentinel, heap_limit);
+ HeapWord* prev_marked = end_of_my_heap + 1;;
+ for (int i = (int) weakly_marked_objects - 1; i >= 0; i--) {
+ // to be renamed get_prev_marked_addr()
+ prev_marked = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1);
+ MarkBitMapAssertEqual(prev_marked, weakly_marked_addresses[i]);
+ MarkBitMapAssertTrue(mbm.is_marked(prev_marked));
+ MarkBitMapAssertTrue(mbm.is_marked_weak(prev_marked));
+ MarkBitMapAssertTrue(!mbm.is_marked_strong(prev_marked));
+ }
+ // We expect no more marked addresses to be found. should return prev_marked.
+ sentinel = mbm.get_prev_marked_addr(&my_heap_memory[0], prev_marked - 1);
+ // MarkBitMapAssertEqual(sentinel, prev_marked);
+ MarkBitMapAssertEqual(sentinel, prev_marked);
+ verify_bitmap_is_weakly_marked(&mbm, weakly_marked_addresses, weakly_marked_objects);
+
+ HeapWord* strongly_marked_addresses[] = {
+ (HeapWord*) &my_heap_memory[8],
+ (HeapWord*) &my_heap_memory[24],
+ (HeapWord*) &my_heap_memory[32],
+ (HeapWord*) &my_heap_memory[56],
+ (HeapWord*) &my_heap_memory[64],
+ (HeapWord*) &my_heap_memory[168],
+ (HeapWord*) &my_heap_memory[232],
+ (HeapWord*) &my_heap_memory[248],
+ (HeapWord*) &my_heap_memory[256],
+ (HeapWord*) &my_heap_memory[257],
+ (HeapWord*) &my_heap_memory[258],
+ (HeapWord*) &my_heap_memory[259],
+ (HeapWord*) &my_heap_memory[488],
+ (HeapWord*) &my_heap_memory[1352],
+ (HeapWord*) &my_heap_memory[1496],
+ (HeapWord*) &my_heap_memory[2432],
+ (HeapWord*) &my_heap_memory[5960]
+ };
+ size_t strongly_marked_objects = sizeof(strongly_marked_addresses) / sizeof(HeapWord*);
+ for (size_t i = 0; i < strongly_marked_objects; i++) {
+ bool upgraded = false;
+ mbm.mark_strong(strongly_marked_addresses[i], upgraded);
+ MarkBitMapAssertTrue(!upgraded);
+ }
+ verify_bitmap_is_strongly_marked(&mbm, strongly_marked_addresses, strongly_marked_objects);
+ HeapWord* upgraded_weakly_marked_addresses[] = {
+ (HeapWord*) &my_heap_memory[240],
+ (HeapWord*) &my_heap_memory[1360],
+ };
+ size_t upgraded_weakly_marked_objects = sizeof(upgraded_weakly_marked_addresses) / sizeof(HeapWord *);
+ for (size_t i = 0; i < upgraded_weakly_marked_objects; i++) {
+ bool upgraded = false;
+ mbm.mark_strong(upgraded_weakly_marked_addresses[i], upgraded);
+ MarkBitMapAssertTrue(upgraded);
+ }
+ verify_bitmap_is_strongly_marked(&mbm, upgraded_weakly_marked_addresses, upgraded_weakly_marked_objects);
+
+ HeapWord* all_marked_addresses[] = {
+ (HeapWord*) &my_heap_memory[8], /* strongly marked */
+ (HeapWord*) &my_heap_memory[13], /* weakly marked */
+ (HeapWord*) &my_heap_memory[14], /* weakly marked */
+ (HeapWord*) &my_heap_memory[15], /* weakly marked */
+ (HeapWord*) &my_heap_memory[16], /* weakly marked */
+ (HeapWord*) &my_heap_memory[24], /* strongly marked */
+ (HeapWord*) &my_heap_memory[32], /* strongly marked */
+ (HeapWord*) &my_heap_memory[56], /* strongly marked */
+ (HeapWord*) &my_heap_memory[64], /* strongly marked */
+ (HeapWord*) &my_heap_memory[168], /* strongly marked */
+ (HeapWord*) &my_heap_memory[176], /* weakly marked */
+ (HeapWord*) &my_heap_memory[232], /* strongly marked */
+ (HeapWord*) &my_heap_memory[240], /* weakly marked upgraded to strongly marked */
+ (HeapWord*) &my_heap_memory[248], /* strongly marked */
+ (HeapWord*) &my_heap_memory[256], /* strongly marked */
+ (HeapWord*) &my_heap_memory[257], /* strongly marked */
+ (HeapWord*) &my_heap_memory[258], /* strongly marked */
+ (HeapWord*) &my_heap_memory[259], /* strongly marked */
+ (HeapWord*) &my_heap_memory[480], /* weakly marked */
+ (HeapWord*) &my_heap_memory[488], /* strongly marked */
+ (HeapWord*) &my_heap_memory[1352], /* strongly marked */
+ (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */
+ (HeapWord*) &my_heap_memory[1488], /* weakly marked */
+ (HeapWord*) &my_heap_memory[1496], /* strongly marked */
+ (HeapWord*) &my_heap_memory[2416], /* weakly marked */
+ (HeapWord*) &my_heap_memory[2432], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5960], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5968], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8191], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8192], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8193] /* weakly marked */
+ };
+ size_t all_marked_objects = sizeof(all_marked_addresses) / sizeof(HeapWord*);
+ bool is_weakly_marked_object[] = {
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true
+ };
+ bool is_strongly_marked_object[] = {
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ verify_bitmap_all(&mbm, all_marked_addresses, is_weakly_marked_object, is_strongly_marked_object, all_marked_objects,
+ my_heap_memory, end_of_my_heap);
+
+ MemRegion first_clear_region(&my_heap_memory[168], &my_heap_memory[256]);
+ mbm.clear_range_large(first_clear_region);
+ // Five objects are no longer marked
+ HeapWord* all_marked_addresses_after_first_clear[] = {
+ (HeapWord*) &my_heap_memory[8], /* strongly marked */
+ (HeapWord*) &my_heap_memory[13], /* weakly marked */
+ (HeapWord*) &my_heap_memory[14], /* weakly marked */
+ (HeapWord*) &my_heap_memory[15], /* weakly marked */
+ (HeapWord*) &my_heap_memory[16], /* weakly marked */
+ (HeapWord*) &my_heap_memory[24], /* strongly marked */
+ (HeapWord*) &my_heap_memory[32], /* strongly marked */
+ (HeapWord*) &my_heap_memory[56], /* strongly marked */
+ (HeapWord*) &my_heap_memory[64], /* strongly marked */
+ (HeapWord*) &my_heap_memory[256], /* strongly marked */
+ (HeapWord*) &my_heap_memory[257], /* strongly marked */
+ (HeapWord*) &my_heap_memory[258], /* strongly marked */
+ (HeapWord*) &my_heap_memory[259], /* strongly marked */
+ (HeapWord*) &my_heap_memory[480], /* weakly marked */
+ (HeapWord*) &my_heap_memory[488], /* strongly marked */
+ (HeapWord*) &my_heap_memory[1352], /* strongly marked */
+ (HeapWord*) &my_heap_memory[1360], /* weakly marked upgraded to strongly marked */
+ (HeapWord*) &my_heap_memory[1488], /* weakly marked */
+ (HeapWord*) &my_heap_memory[1496], /* strongly marked */
+ (HeapWord*) &my_heap_memory[2416], /* weakly marked */
+ (HeapWord*) &my_heap_memory[2432], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5960], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5968], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8191], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8192], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8193] /* weakly marked */
+ };
+ size_t all_marked_objects_after_first_clear = sizeof(all_marked_addresses_after_first_clear) / sizeof(HeapWord*);
+ bool is_weakly_marked_object_after_first_clear[] = {
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true
+ };
+ bool is_strongly_marked_object_after_first_clear[] = {
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ verify_bitmap_all(&mbm, all_marked_addresses_after_first_clear,
+ is_weakly_marked_object_after_first_clear, is_strongly_marked_object_after_first_clear,
+ all_marked_objects_after_first_clear, my_heap_memory, end_of_my_heap);
+
+ MemRegion second_clear_region(&my_heap_memory[1360], &my_heap_memory[2416]);
+ mbm.clear_range_large(second_clear_region);
+ // Five objects are no longer marked
+ HeapWord* all_marked_addresses_after_2nd_clear[] = {
+ (HeapWord*) &my_heap_memory[8], /* strongly marked */
+ (HeapWord*) &my_heap_memory[13], /* weakly marked */
+ (HeapWord*) &my_heap_memory[14], /* weakly marked */
+ (HeapWord*) &my_heap_memory[15], /* weakly marked */
+ (HeapWord*) &my_heap_memory[16], /* weakly marked */
+ (HeapWord*) &my_heap_memory[24], /* strongly marked */
+ (HeapWord*) &my_heap_memory[32], /* strongly marked */
+ (HeapWord*) &my_heap_memory[56], /* strongly marked */
+ (HeapWord*) &my_heap_memory[64], /* strongly marked */
+ (HeapWord*) &my_heap_memory[256], /* strongly marked */
+ (HeapWord*) &my_heap_memory[257], /* strongly marked */
+ (HeapWord*) &my_heap_memory[258], /* strongly marked */
+ (HeapWord*) &my_heap_memory[259], /* strongly marked */
+ (HeapWord*) &my_heap_memory[480], /* weakly marked */
+ (HeapWord*) &my_heap_memory[488], /* strongly marked */
+ (HeapWord*) &my_heap_memory[1352], /* strongly marked */
+ (HeapWord*) &my_heap_memory[2416], /* weakly marked */
+ (HeapWord*) &my_heap_memory[2432], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5960], /* strongly marked */
+ (HeapWord*) &my_heap_memory[5968], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8191], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8192], /* weakly marked */
+ (HeapWord*) &my_heap_memory[8193] /* weakly marked */
+ };
+ size_t all_marked_objects_after_2nd_clear = sizeof(all_marked_addresses_after_2nd_clear) / sizeof(HeapWord*);
+ bool is_weakly_marked_object_after_2nd_clear[] = {
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true
+ };
+ bool is_strongly_marked_object_after_2nd_clear[] = {
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ verify_bitmap_all(&mbm, all_marked_addresses_after_2nd_clear,
+ is_weakly_marked_object_after_2nd_clear, is_strongly_marked_object_after_2nd_clear,
+ all_marked_objects_after_2nd_clear, my_heap_memory, end_of_my_heap);
+
+ FREE_C_HEAP_ARRAY(HeapWord, my_bitmap_memory);
+ _success = true;
+ return true;
+ }
+};
+
+TEST_VM_F(ShenandoahMarkBitMapTest, minimum_test) {
+ SKIP_IF_NOT_SHENANDOAH();
+
+ bool result = ShenandoahMarkBitMapTest::run_test();
+ ASSERT_EQ(result, true);
+ ASSERT_EQ(_success, true);
+ ASSERT_EQ(_assertion_failures, (size_t) 0);
+}
diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp
index 3a5e0662b0c..2fd87b48dc2 100644
--- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp
+++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp
@@ -52,7 +52,7 @@ class ShenandoahOldGenerationTest : public ::testing::Test {
ShenandoahHeap::heap()->lock()->lock(false);
- old = new ShenandoahOldGeneration(8, 1024 * 1024, 1024);
+ old = new ShenandoahOldGeneration(8, 1024 * 1024);
old->set_promoted_reserve(512 * HeapWordSize);
old->expend_promoted(256 * HeapWordSize);
old->set_evacuation_reserve(512 * HeapWordSize);
diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp
index d08cfd7618b..7b633338c1f 100644
--- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp
+++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldHeuristic.cpp
@@ -49,7 +49,7 @@
#else
#define SKIP_IF_NOT_SHENANDOAH() \
if (!UseShenandoahGC) { \
- tty->print_cr("skipped"); \
+ std::cout << "skipped\n"; \
return; \
}
#endif
diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt
index 6df68c1ed62..393a33d3eae 100644
--- a/test/hotspot/jtreg/ProblemList-Xcomp.txt
+++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt
@@ -52,6 +52,4 @@ vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 829
vmTestbase/nsk/stress/thread/thread006.java 8321476 linux-all
-compiler/cha/TypeProfileFinalMethod.java 8341039 generic-all
-
gc/arguments/TestNewSizeFlags.java 8299116 macosx-aarch64
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index c0f762fa785..26198afba6c 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -66,6 +66,7 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8
compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8331704 linux-riscv64
compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8331704 linux-riscv64
compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8331704 linux-riscv64
+compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java 8360168 linux-riscv64
compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586
compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586
diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java
index b1186a85cae..01769470d78 100644
--- a/test/hotspot/jtreg/compiler/c2/TestBit.java
+++ b/test/hotspot/jtreg/compiler/c2/TestBit.java
@@ -33,7 +33,7 @@
* @library /test/lib /
*
* @requires vm.flagless
- * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64"
+ * @requires os.arch == "aarch64" | os.arch == "amd64" | os.arch == "x86_64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64"
* @requires vm.debug == true & vm.compiler2.enabled
*
* @run driver compiler.c2.TestBit
diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java
new file mode 100644
index 00000000000..605f65eb00c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresAndAllocationElimination.java
@@ -0,0 +1,123 @@
+/*
+ * 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.c2;
+
+/*
+ * @test
+ * @bug 8370405
+ * @summary Test case where we had escape analysis tell us that we can possibly eliminate
+ * the array allocation, then MergeStores introduces a mismatched store, which
+ * the actual elimination does not verify for. That led to wrong results.
+ * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestMergeStoresAndAllocationElimination::test
+ * -XX:CompileCommand=exclude,compiler.c2.TestMergeStoresAndAllocationElimination::dontinline
+ * -XX:-TieredCompilation -Xbatch
+ * -XX:+IgnoreUnrecognizedVMOptions -XX:-CICompileOSR
+ * compiler.c2.TestMergeStoresAndAllocationElimination
+ * @run main compiler.c2.TestMergeStoresAndAllocationElimination
+ */
+
+public class TestMergeStoresAndAllocationElimination {
+ static void dontinline() {}
+
+ static int test(boolean flag) {
+ int[] arr = new int[4];
+ // The values below will be caputured as "raw stores" in the Initialize
+ // of the array allocation above.
+ // These stores are for cosmetics only, we set the "1" bits so that it is
+ // simple to track where values are coming from.
+ arr[0] = 0x0001_0000;
+ arr[1] = 0x0010_0000;
+ arr[2] = 0x0000_0100;
+ arr[3] = 0x0100_0000;
+ // So far, the result should be:
+ // 0x421_0300
+
+ // The call below prevents further assignments from being captured into
+ // the Initialize above.
+ dontinline();
+ // The follwoing stores are eventually optimized by MergeStores, and create
+ // a mismatched StoreL.
+ arr[0] = 0x0000_0001;
+ arr[1] = 0x0000_0010;
+ // Now, the result should be:
+ // 0x400_0321
+
+ // We create an uncommon trap because of an "unstable if".
+ // If Escape Analysis were to work, it would try to capture the values
+ // from the StoreL above. But because it is mismatched, it should fail.
+ // What happened before that verification: we would take the ConL, and
+ // insert it in a list of ConI. That meant that we eventually applied
+ // that value wrong if the deopt was taken (flag = true).
+ //
+ // What happened when the deopt got the wrong values: It got these values:
+ // [0]=68719476737 = 0x10_0000_0001 -> long value, not correct
+ // [1]=1048576 = 0x10_0000 -> this entry is not updated!
+ // [2]=256 = 0x100
+ // [3]=16777216 = 0x100_0000
+ //
+ // This is serialized as a long and 3 ints, and that looks like 5 ints.
+ // This creates an array of 5 elements (and not 4):
+ // [0] = 0x1
+ // [1] = 0x10
+ // [2] = 0x10_0000 -> this entry is "inserted"
+ // [3] = 0x100
+ // [4] = 0x100_0000
+ //
+ // This creates the wrong state:
+ // 0x30_0421
+ // And we can actually read that the arr.length is 5, below.
+ if (flag) { System.out.println("unstable if: " + arr.length); }
+
+ // Delay the allocation elimination until after loop opts, so that it
+ // happens after MergeStores. Without this, we would immediately
+ // eliminate the allocation during Escape Analysis, and then MergeStores
+ // would not find the stores that would be removed with the allocation.
+ for (int i = 0; i < 10_000; i++) {
+ arr[3] = 0x0000_1000;
+ }
+ // Coming from the correct value, we should have transition of state:
+ // 0x400_0321 -> 0x4321
+ // But coming from the bad (rematerialized) state, we transition:
+ // 0x30_0421 -> 0x30_4021
+
+ // Tag each entry with an index number
+ // We expect: 0x4321
+ return 1 * arr[0] + 2 * arr[1] + 3 * arr[2] + 4 * arr[3];
+ }
+
+ public static void main(String[] args) {
+ // Capture interpreter result.
+ int gold = test(false);
+ // Repeat until we get compilation.
+ for (int i = 0; i < 10_000; i++) {
+ test(false);
+ }
+ // Capture compiled results.
+ int res0 = test(false);
+ int res1 = test(true);
+ if (res0 != gold || res1 != gold) {
+ throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " + Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold));
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java
index e3651129daa..f5225e8173c 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 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
@@ -31,7 +31,7 @@
* @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected.
* @library /test/lib /
* @run driver compiler.c2.irTests.RotateLeftNodeIntIdealizationTests
- * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*")
+ * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*")
*/
public class RotateLeftNodeIntIdealizationTests {
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java
index 190f08d348c..b28d2f6dc8b 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 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
@@ -31,7 +31,7 @@
* @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected.
* @library /test/lib /
* @run driver compiler.c2.irTests.RotateLeftNodeLongIdealizationTests
- * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*")
+ * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*")
*/
public class RotateLeftNodeLongIdealizationTests {
diff --git a/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java b/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java
index a81ba53af52..8958a195653 100644
--- a/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java
+++ b/test/hotspot/jtreg/compiler/cha/TypeProfileFinalMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -25,7 +25,7 @@
/*
* @test
* @summary test c1 to record type profile with CHA optimization
- * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
+ * @requires vm.flavor == "server" & vm.flagless
* @library /test/lib
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
@@ -48,6 +48,7 @@ public static void main(String[] args) throws Exception {
"-Xbatch", "-XX:-UseOnStackReplacement",
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-XX:Tier3InvocationThreshold=200", "-XX:Tier4InvocationThreshold=5000",
+ "-XX:CompileCommand=CompileOnly," + Launcher.class.getName() + "::test*",
Launcher.class.getName());
OutputAnalyzer output = ProcessTools.executeProcess(pb);
System.out.println("debug output");
@@ -61,7 +62,7 @@ public static void main(String[] args) throws Exception {
while (matcher.find()) {
matchCnt++;
}
- Asserts.assertEquals(matchCnt, 2); // inline Child1::m() twice
+ Asserts.assertEquals(2, matchCnt); // inline Child1::m() twice
}
static class Launcher {
@@ -86,23 +87,23 @@ public static void main(String[] args) throws Exception {
static void addCompilerDirectives() {
WhiteBox WB = WhiteBox.getWhiteBox();
- // do not inline getInstance() for test1() and test2()
+ // Directive for test1
String directive = "[{ match: [\"" + Launcher.class.getName() + "::test1\"]," +
- "inline:[\"-" + Launcher.class.getName()+"::getInstance()\"] }]";
+ // Do not inline getInstance
+ "inline:[\"-" + Launcher.class.getName()+"::getInstance\"] }]";
WB.addCompilerDirective(directive);
+ // Directive for test2
directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," +
- "inline:[\"-" + Launcher.class.getName()+"::getInstance()\"] }]";
- WB.addCompilerDirective(directive);
-
- // do not inline test1() for test2() in c1 compilation
- directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," +
- "c1: { inline:[\"-" + Launcher.class.getName()+"::test1()\"] } }]";
- WB.addCompilerDirective(directive);
-
- // print inline tree for checking
- directive = "[{ match: [\"" + Launcher.class.getName() + "::test2\"]," +
- "c2: { PrintInlining: true } }]";
+ // Do not inline getInstance
+ "inline:[\"-" + Launcher.class.getName()+"::getInstance\"]," +
+ // Do not inline test1 in C1 compilation
+ "c1: { inline:[\"-" + Launcher.class.getName()+"::test1\"] }," +
+ // Make sure to inline test1 in C2 compilation
+ "c2: { inline:[\"+" + Launcher.class.getName()+"::test1\"]," +
+ // Print the inline tree for checking
+ " PrintInlining:true }" +
+ "}]";
WB.addCompilerDirective(directive);
}
diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java
new file mode 100644
index 00000000000..d2fdf47b060
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestRematerializeObjects.java
@@ -0,0 +1,195 @@
+/*
+ * 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 id=yEA
+ * @bug 8370405
+ * @summary Test elimination of array allocation, and the rematerialization.
+ * @library /test/lib /
+ * @run driver compiler.escapeAnalysis.TestRematerializeObjects yEA
+ */
+
+/*
+ * @test id=nEA
+ * @library /test/lib /
+ * @run driver compiler.escapeAnalysis.TestRematerializeObjects nEA
+ */
+
+package compiler.escapeAnalysis;
+
+import jdk.test.lib.Utils;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.verify.*;
+
+public class TestRematerializeObjects {
+
+ public static void main(String[] args) {
+ TestFramework framework = new TestFramework(TestRematerializeObjects.class);
+ switch (args[0]) {
+ case "yEA" -> { framework.addFlags("-XX:+EliminateAllocations"); }
+ case "nEA" -> { framework.addFlags("-XX:-EliminateAllocations"); }
+ default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); }
+ };
+ framework.start();
+ }
+
+ @DontInline
+ static void dontinline() {}
+
+ @Run(test = "test1", mode = RunMode.STANDALONE)
+ public void runTest1() {
+ // Capture interpreter result.
+ int gold = test1(false);
+ // Repeat until we get compilation.
+ for (int i = 0; i < 10_000; i++) {
+ test1(false);
+ }
+ // Capture compiled results.
+ int res0 = test1(false);
+ int res1 = test1(true);
+ if (res0 != gold || res1 != gold) {
+ throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " +
+ Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold));
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.ALLOC_ARRAY, "1",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.STORE_L_OF_CLASS, "int\\[int:4\\]", "1",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"},
+ applyIfAnd = {"EliminateAllocations", "false", "UseUnalignedAccesses", "true"})
+ @IR(counts = {IRNode.ALLOC_ARRAY, "0",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.STORE_L_OF_CLASS, "int\\[int:4\\]", "0",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"},
+ applyIfAnd = {"EliminateAllocations", "true", "UseUnalignedAccesses", "true"})
+ static int test1(boolean flag) {
+ int[] arr = new int[4];
+ arr[0] = 0x0001_0000; // these slip into Initialize
+ arr[1] = 0x0010_0000;
+ arr[2] = 0x0000_0100;
+ arr[3] = 0x0100_0000;
+ dontinline();
+ arr[0] = 0x0000_0001; // MergeStores -> StoreL
+ arr[1] = 0x0000_0010;
+ if (flag) {
+ // unstable if -> deopt -> rematerialized array (if was eliminated)
+ System.out.println("unstable if: " + arr.length);
+ }
+ arr[3] = 0x0000_1000;
+ return 1 * arr[0] + 2 * arr[1] + 3 * arr[2] + 4 * arr[3];
+ }
+
+ @Run(test = "test2", mode = RunMode.STANDALONE)
+ public void runTest2() {
+ // Capture interpreter result.
+ int gold = test2(false);
+ // Repeat until we get compilation.
+ for (int i = 0; i < 10_000; i++) {
+ test2(false);
+ }
+ // Capture compiled results.
+ int res0 = test2(false);
+ int res1 = test2(true);
+ if (res0 != gold || res1 != gold) {
+ throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " +
+ Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold));
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.ALLOC_ARRAY, "1",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.STORE_I_OF_CLASS, "short\\[int:4\\]", "1",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"},
+ applyIfAnd = {"EliminateAllocations", "false", "UseUnalignedAccesses", "true"})
+ @IR(counts = {IRNode.ALLOC_ARRAY, "0",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.STORE_I_OF_CLASS, "short\\[int:4\\]", "0",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"},
+ applyIfAnd = {"EliminateAllocations", "true", "UseUnalignedAccesses", "true"})
+ static int test2(boolean flag) {
+ short[] arr = new short[4];
+ arr[0] = 1;
+ arr[1] = 2;
+ arr[2] = 4;
+ arr[3] = 8;
+ dontinline();
+ // Seems we detect that this is a short value passed into the short field.
+ arr[0] = 16;
+ arr[1] = 32;
+ if (flag) {
+ // unstable if -> deopt -> rematerialized array (if was eliminated)
+ System.out.println("unstable if: " + arr.length);
+ }
+ arr[3] = 64;
+ return 0x1 * arr[0] + 0x100 * arr[1] + 0x1_0000 * arr[2] + 0x100_0000 * arr[3];
+ }
+
+ @Run(test = "test3", mode = RunMode.STANDALONE)
+ public void runTest3() {
+ // Capture interpreter result.
+ int gold = test3(false, 42);
+ // Repeat until we get compilation.
+ for (int i = 0; i < 10_000; i++) {
+ test3(false, 42);
+ }
+ // Capture compiled results.
+ int res0 = test3(false, 42);
+ int res1 = test3(true, 42);
+ if (res0 != gold || res1 != gold) {
+ throw new RuntimeException("Unexpected result: " + Integer.toHexString(res0) + " and " +
+ Integer.toHexString(res1) + ", should be: " + Integer.toHexString(gold));
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.ALLOC_ARRAY, "1",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "0"},
+ applyIf = {"EliminateAllocations", "false"})
+ @IR(counts = {IRNode.ALLOC_ARRAY, "0",
+ IRNode.UNSTABLE_IF_TRAP, "1",
+ IRNode.SAFEPOINT_SCALAROBJECT_OF, "fields@\\[0..3\\]", "2"},
+ applyIf = {"EliminateAllocations", "true"})
+ static int test3(boolean flag, int x) {
+ short[] arr = new short[4];
+ arr[0] = 1;
+ arr[1] = 2;
+ arr[2] = 4;
+ arr[3] = 8;
+ dontinline();
+ // Here, we don't get ConI, but instead AddI, which means we are
+ // serializing an int value, for a short slot.
+ arr[0] = (short)(x + 1);
+ arr[1] = (short)(x + 2);
+ if (flag) {
+ // unstable if -> deopt -> rematerialized array (if was eliminated)
+ System.out.println("unstable if: " + arr.length);
+ }
+ arr[3] = 64;
+ return 0x1 * arr[0] + 0x100 * arr[1] + 0x1_0000 * arr[2] + 0x100_0000 * arr[3];
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java
index 4c7092ec654..d96e64baa36 100644
--- a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java
+++ b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java
@@ -38,7 +38,13 @@
public class TestSubNodeFloatDoubleNegation {
public static void main(String[] args) {
- TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:CompileCommand=inline,jdk.incubator.vector.Float16::*");
+ // Disable inlining for java.lang.Float::float16ToFloat and java.lang.Float::floatToFloat16.
+ // Otherwise, they could be inlined into testHalfFloat on platforms where there is no support
+ // for fp16, which causes unexpected IR graph.
+ TestFramework.runWithFlags("--add-modules=jdk.incubator.vector",
+ "-XX:CompileCommand=inline,jdk.incubator.vector.Float16::*",
+ "-XX:CompileCommand=dontinline,java.lang.Float::float16ToFloat",
+ "-XX:CompileCommand=dontinline,java.lang.Float::floatToFloat16");
}
@Run(test = { "testHalfFloat", "testFloat", "testDouble" })
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java
index 2d4d4353868..22b3bba854c 100644
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -120,7 +120,7 @@ public static BooleanSupplier getPredicateForOption(String optionName) {
case DigestOptionsBase.USE_SHA256_INTRINSICS_OPTION:
return IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE;
case DigestOptionsBase.USE_SHA512_INTRINSICS_OPTION:
- return IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE;
+ return IntrinsicPredicates.isSHA512IntrinsicAvailable();
case DigestOptionsBase.USE_SHA3_INTRINSICS_OPTION:
return IntrinsicPredicates.SHA3_INSTRUCTION_AVAILABLE;
default:
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java
index e349c22e383..7913a25d939 100644
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -25,7 +25,6 @@
* @test
* @bug 8035968
* @summary Verify UseSHA512Intrinsics option processing on supported CPU.
- * @requires os.arch!="x86" & os.arch!="i386"
* @library /test/lib /
* @requires vm.flagless
*
diff --git a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
index 4285000e27f..4c8e63d0a42 100644
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
@@ -229,8 +229,8 @@ public static void reprofile(HotSpotResolvedJavaMethod method) {
CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method);
}
- public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize) {
- CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize);
+ public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason) {
+ CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize, invalidationReason);
}
public static long[] collectCounters() {
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java
new file mode 100644
index 00000000000..624a2290509
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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
+ * @requires vm.jvmci
+ * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
+ * @library /test/lib /
+ * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
+ * jdk.internal.vm.ci/jdk.vm.ci.meta
+ * jdk.internal.vm.ci/jdk.vm.ci.code
+ * jdk.internal.vm.ci/jdk.vm.ci.code.site
+ * jdk.internal.vm.ci/jdk.vm.ci.runtime
+ * jdk.internal.vm.ci/jdk.vm.ci.aarch64
+ * jdk.internal.vm.ci/jdk.vm.ci.amd64
+ * jdk.internal.vm.ci/jdk.vm.ci.riscv64
+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.CodeInvalidationReasonTest
+ */
+
+package jdk.vm.ci.code.test;
+
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.hotspot.HotSpotNmethod;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+/**
+ * Test if setting HotSpotNmethod invalidation reason around works.
+ */
+public class CodeInvalidationReasonTest extends CodeInstallationTest {
+
+ public static int add(int a, int b) {
+ return a + b;
+ }
+
+ private static void compileAdd(TestAssembler asm) {
+ Register arg0 = asm.emitIntArg0();
+ Register arg1 = asm.emitIntArg1();
+ Register ret = asm.emitIntAdd(arg0, arg1);
+ asm.emitIntRet(ret);
+ }
+
+ @Test
+ public void test() {
+ Method method = getMethod("add", int.class, int.class);
+
+ HotSpotNmethod nmethod = test(CodeInvalidationReasonTest::compileAdd, method, 5, 7);
+ Asserts.assertEquals(-1 /* since it was not invalidated yet. */, nmethod.getInvalidationReason());
+
+ nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE);
+ Asserts.assertEquals(config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE, nmethod.getInvalidationReason());
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java
index c9c88024d99..4c76aea7a40 100644
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java
@@ -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
@@ -71,13 +71,13 @@ public void test() {
Asserts.assertNotEquals(nmethod.getStart(), 0L);
// Make nmethod non-entrant but still alive
- nmethod.invalidate(false);
+ nmethod.invalidate(false, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE);
Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod);
Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod);
Asserts.assertEquals(nmethod.getStart(), 0L);
// Deoptimize the nmethod and cut the link to it from the HotSpotNmethod
- nmethod.invalidate(true);
+ nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE);
Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod);
Asserts.assertFalse(nmethod.isAlive(), "code is alive, i = " + nmethod);
Asserts.assertEquals(nmethod.getStart(), 0L);
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java
index db30229d34f..a26872b96ae 100644
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -55,6 +55,8 @@ public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) {
public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int");
public final int heapWordSize = getConstant("HeapWordSize", Integer.class);
+ public final int NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE = getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class);
+
public final boolean ropProtection;
private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) {
@@ -65,7 +67,7 @@ private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) {
// There currently only 2 variants in use that differ only by the presence of a
// dmb instruction
int stw = getConstant("NMethodPatchingType::stw_instruction_and_data_patch", Integer.class);
- int conc = getConstant("NMethodPatchingType::conc_data_patch", Integer.class);
+ int conc = getConstant("NMethodPatchingType::conc_instruction_and_data_patch", Integer.class);
if (patchingType == stw) {
patchConcurrent = false;
} else if (patchingType == conc) {
diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java
index d160bf319d8..b5729aeec7d 100644
--- a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java
+++ b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java
@@ -35,6 +35,9 @@ final class UniformDoubleGenerator extends UniformIntersectionRestrictableGenera
*/
public UniformDoubleGenerator(Generators g, double lo, double hi) {
super(g, lo, hi);
+ if (Double.compare(lo, hi) >= 0) {
+ throw new EmptyGeneratorException();
+ }
}
@Override
diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java
index 1b72ad5adc9..4405b120619 100644
--- a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java
+++ b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java
@@ -35,6 +35,9 @@ final class UniformFloatGenerator extends UniformIntersectionRestrictableGenerat
*/
public UniformFloatGenerator(Generators g, float lo, float hi) {
super(g, lo, hi);
+ if (Float.compare(lo, hi) >= 0) {
+ throw new EmptyGeneratorException();
+ }
}
@Override
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
index f53bb45bd43..030a70e2e6c 100644
--- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
@@ -102,8 +102,6 @@ public class IRNode {
private static final String START = "(\\d+(\\s){2}(";
private static final String MID = ".*)+(\\s){2}===.*";
private static final String END = ")";
- private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
- private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
public static final String IS_REPLACED = "#IS_REPLACED#"; // Is replaced by an additional user-defined string.
@@ -1820,6 +1818,11 @@ public class IRNode {
optoOnly(SCOPE_OBJECT, regex);
}
+ public static final String SAFEPOINT_SCALAROBJECT_OF = COMPOSITE_PREFIX + "SAFEPOINT_SCALAROBJECT_OF" + POSTFIX;
+ static {
+ safepointScalarobjectOfNodes(SAFEPOINT_SCALAROBJECT_OF, "SafePointScalarObject");
+ }
+
public static final String SIGNUM_VD = VECTOR_PREFIX + "SIGNUM_VD" + POSTFIX;
static {
vectorNode(SIGNUM_VD, "SignumVD", TYPE_DOUBLE);
@@ -2938,13 +2941,30 @@ private static void parsePredicateNodes(String irNodePlaceholder, String label)
CompilePhase.AFTER_LOOP_OPTS));
}
+ // Typename in load/store have the structure:
+ // @fully/qualified/package/name/to/TheClass+12 *
+ // And variation:
+ // - after @, we can have "stable:" or other labels, with optional space after ':'
+ // - the class can actually be a subclass, with $ separator (and it must be ok to give only the deepest one
+ // - after the class name, we can have a comma-separated list of implemented interfaces enclosed in parentheses
+ // - before the offset, we can have something like ":NotNull", either way, seeing "+" or ":" means the end of the type
+ // Worst case, it can be something like:
+ // @bla: bli:a/b/c$d$e (f/g,h/i/j):NotNull+24 *
+ private static final String LOAD_STORE_PREFIX = "@(\\w+: ?)*[\\w/\\$]*\\b";
+ private static final String LOAD_STORE_SUFFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*";
+
private static void loadOfNodes(String irNodePlaceholder, String irNodeRegex) {
- String regex = START + irNodeRegex + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
+ String regex = START + irNodeRegex + MID + LOAD_STORE_PREFIX + IS_REPLACED + LOAD_STORE_SUFFIX + END;
beforeMatching(irNodePlaceholder, regex);
}
private static void storeOfNodes(String irNodePlaceholder, String irNodeRegex) {
- String regex = START + irNodeRegex + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
+ String regex = START + irNodeRegex + MID + LOAD_STORE_PREFIX + IS_REPLACED + LOAD_STORE_SUFFIX + END;
+ beforeMatching(irNodePlaceholder, regex);
+ }
+
+ private static void safepointScalarobjectOfNodes(String irNodePlaceholder, String irNodeRegex) {
+ String regex = START + irNodeRegex + MID + ".*" + IS_REPLACED + ".*" + END;
beforeMatching(irNodePlaceholder, regex);
}
diff --git a/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java
new file mode 100644
index 00000000000..39f72b04139
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java
@@ -0,0 +1,114 @@
+/*
+ * 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 8373525
+ * @summary Test for the check of a valid type (long) for the input variable of overflow protection
+ * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,compiler.loopopts.TestValidTypeInOverflowProtection::test
+ * ${test.main.class}
+ * @run main ${test.main.class}
+ */
+
+package compiler.loopopts;
+
+import java.util.Vector;
+
+class TestVector extends Vector {
+ TestVector(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ Object getElementData() {
+ return elementData;
+ }
+}
+
+public class TestValidTypeInOverflowProtection {
+ int cntr;
+ int mode;
+ int value = 533;
+ int one = 1;
+
+ public static void main(String[] args) {
+ TestValidTypeInOverflowProtection test = new TestValidTypeInOverflowProtection();
+ for (int i = 0; i < 1000; i++) {
+ test.test();
+ }
+ }
+
+ TestVector nextVector() {
+ if (cntr == one) {
+ return null;
+ }
+ TestVector vect = new TestVector(value);
+ if (mode == 2) {
+ int cap = vect.capacity();
+ for (int i = 0; i < cap; i++) {
+ vect.addElement(new Object());
+ }
+ }
+ if (++mode == 3) {
+ mode = cntr++;
+ }
+ return vect;
+ }
+
+ String test() {
+ cntr = 0;
+ TestVector vect = nextVector();
+ while (vect != null) {
+ Object backup_array = new Object[vect.size()];
+ System.arraycopy(vect.getElementData(), 0, backup_array, 0, vect.size());
+ int old_size = vect.size();
+ int old_cap = vect.capacity();
+ vect.setSize(vect.capacity() + 1);
+ for (int i = old_size; i < old_cap; i++) {
+ if (vect.elementAt(i) != null) {
+ }
+ }
+ for (int i = 0; i < new MyInteger(old_size).v; i++) {
+ }
+ vect = nextVector();
+ }
+ return null;
+ }
+
+ class MyInteger {
+ int v;
+
+ MyInteger(int v) {
+ int M452 = 4;
+ int N452 = 8;
+ for (int i452 = 0; i452 < M452; i452++) {
+ for (int j452 = 0; j452 < N452; j452++) {
+ switch (i452) {
+ case -2:
+ case 0:
+ this.v = v;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java
index 9c3e2c7bc5d..f1e68fb95fb 100644
--- a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java
+++ b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Long.java
@@ -31,16 +31,21 @@
package compiler.loopopts.superword;
-import compiler.lib.ir_framework.*;
-import jdk.test.lib.Utils;
+import compiler.lib.generators.Generator;
+import compiler.lib.generators.Generators;
+import compiler.lib.ir_framework.IR;
+import compiler.lib.ir_framework.IRNode;
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.RunMode;
+import compiler.lib.ir_framework.Test;
+import compiler.lib.ir_framework.TestFramework;
import java.util.Arrays;
-import java.util.Random;
-import java.util.stream.LongStream;
public class MinMaxRed_Long {
- private static final Random random = Utils.getRandomInstance();
+ private static final int SIZE = 1024;
+ private static final Generator GEN_LONG = Generators.G.longs();
public static void main(String[] args) throws Exception {
TestFramework framework = new TestFramework();
@@ -53,97 +58,41 @@ public static void main(String[] args) throws Exception {
@Run(test = {"maxReductionImplement"},
mode = RunMode.STANDALONE)
public void runMaxTest() {
- runMaxTest(50);
- runMaxTest(80);
- runMaxTest(100);
- }
+ long[] longs = new long[SIZE];
+ Generators.G.fill(GEN_LONG, longs);
- private static void runMaxTest(int probability) {
- long[] longs = reductionInit(probability);
long res = 0;
for (int j = 0; j < 2000; j++) {
res = maxReductionImplement(longs, res);
}
- if (res == 11 * Arrays.stream(longs).max().getAsLong()) {
+
+ final long expected = Arrays.stream(longs).map(l -> l * 11).max().getAsLong();
+ if (res == expected) {
System.out.println("Success");
} else {
- throw new AssertionError("Failed");
+ throw new AssertionError("Failed, got result " + res + " but expected " + expected);
}
}
@Run(test = {"minReductionImplement"},
mode = RunMode.STANDALONE)
public void runMinTest() {
- runMinTest(50);
- runMinTest(80);
- runMinTest(100);
- }
+ long[] longs = new long[SIZE];
+ Generators.G.fill(GEN_LONG, longs);
- private static void runMinTest(int probability) {
- long[] longs = reductionInit(probability);
- // Negating the values generated for controlling max branching
- // allows same logic to be used for min tests.
- longs = negate(longs);
long res = 0;
for (int j = 0; j < 2000; j++) {
res = minReductionImplement(longs, res);
}
- if (res == 11 * Arrays.stream(longs).min().getAsLong()) {
+
+ final long expected = Arrays.stream(longs).map(l -> l * 11).min().getAsLong();
+ if (res == expected) {
System.out.println("Success");
} else {
- throw new AssertionError("Failed");
+ throw new AssertionError("Failed, got result " + res + " but expected " + expected);
}
}
- static long[] negate(long[] nums) {
- return LongStream.of(nums).map(l -> -l).toArray();
- }
-
- public static long[] reductionInit(int probability) {
- int aboveCount, abovePercent;
- long[] longs = new long[1024];
-
- // Generates an array of numbers such that as the array is iterated
- // there is P probability of finding a new max value,
- // and 100-P probability of not finding a new max value.
- // The algorithm loops around if the distribution does not match the probability,
- // but it approximates the probability as the array sizes increase.
- // The worst case of this algorithm is when the desired array size is 100
- // and the aim is to get 50% of probability, which can only be satisfied
- // with 50 elements being a new max. This situation can take 15 rounds.
- // As sizes increase, say 10'000 elements,
- // the number of elements that have to satisfy 50% increases,
- // so the algorithm will stop as an example when 5027 elements are a new max values.
- // Also, probability values in the edges will achieve their objective quicker,
- // with 0% or 100% probability doing it in a single loop.
- // To support the same algorithm for min calculations,
- // negating the array elements achieves the same objective.
- do {
- long max = random.nextLong(10);
- longs[0] = max;
-
- aboveCount = 0;
- for (int i = 1; i < longs.length; i++) {
- long value;
- if (random.nextLong(101) <= probability) {
- long increment = random.nextLong(10);
- value = max + increment;
- aboveCount++;
- } else {
- // Decrement by at least 1
- long diffToMax = random.nextLong(10) + 1;
- value = max - diffToMax;
- }
- longs[i] = value;
- max = Math.max(max, value);
- }
-
- abovePercent = ((aboveCount + 1) * 100) / longs.length;
- } while (abovePercent != probability);
-
- return longs;
- }
-
@Test
@IR(applyIfAnd = {"SuperWordReductions", "true", "MaxVectorSize", ">=32"},
applyIfCPUFeatureOr = {"avx512", "true", "asimd" , "true"},
diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java
index d75db965ea3..019dad55b65 100644
--- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java
+++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.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
@@ -30,7 +30,19 @@
* @key randomness
* @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions
* -XX:LoopUnrollLimit=250
- * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::*
+ * compiler.loopopts.superword.TestAlignVectorFuzzer
+ */
+
+/*
+ * @test id=CompileOnly
+ * @bug 8253191
+ * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Do not force alignment.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @key randomness
+ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:LoopUnrollLimit=250
+ * -XX:CompileCommand=compileonly,compiler.loopopts.superword.TestAlignVectorFuzzer::*
* compiler.loopopts.superword.TestAlignVectorFuzzer
*/
@@ -44,7 +56,6 @@
* @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions
* -XX:+AlignVector -XX:+VerifyAlignVector
* -XX:LoopUnrollLimit=250
- * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::*
* compiler.loopopts.superword.TestAlignVectorFuzzer
*/
@@ -58,7 +69,6 @@
* @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions
* -XX:+AlignVector -XX:+VerifyAlignVector
* -XX:LoopUnrollLimit=250
- * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::*
* -XX:ObjectAlignmentInBytes=16
* compiler.loopopts.superword.TestAlignVectorFuzzer
*/
@@ -73,7 +83,6 @@
* @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions
* -XX:+AlignVector -XX:+VerifyAlignVector
* -XX:LoopUnrollLimit=250
- * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::*
* -XX:-TieredCompilation -Xbatch
* compiler.loopopts.superword.TestAlignVectorFuzzer
*/
diff --git a/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java b/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java
index 9e8ac6b013a..1091037cdfb 100644
--- a/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java
+++ b/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java
@@ -42,8 +42,8 @@ public static void main(String args[]) throws Exception {
"-XX:+SafepointTimeout",
"-XX:+SafepointALot",
"-XX:+AbortVMOnSafepointTimeout",
- "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300),
- "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300),
+ "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200),
+ "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200),
"-XX:-TieredCompilation",
"-XX:+UseCountedLoopSafepoints",
"-XX:LoopStripMiningIter=1000",
@@ -58,8 +58,8 @@ public static void main(String args[]) throws Exception {
"-XX:+SafepointTimeout",
"-XX:+SafepointALot",
"-XX:+AbortVMOnSafepointTimeout",
- "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300),
- "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300),
+ "-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200),
+ "-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200),
"-XX:-TieredCompilation",
"-XX:+UseCountedLoopSafepoints",
"-XX:LoopStripMiningIter=1000",
diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
index 22f2887a266..bb08a2c0a2d 100644
--- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java
+++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
@@ -36,6 +36,7 @@
package compiler.startup;
+import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Utils;
@@ -60,8 +61,11 @@ public static void main(String[] args) throws Exception {
throw new Exception("VM crashed with exit code " + exitCode);
}
- for (int i = 0; i < 200; i++) {
- int initialCodeCacheSizeInKb = 800 + rand.nextInt(400);
+ // 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 < 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");
out = new OutputAnalyzer(pb.start());
diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java
index a9de46e00b0..efe1fa4ffbc 100644
--- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java
+++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java
@@ -77,7 +77,7 @@ public static void main(String[] args) throws Exception {
throw new SkippedException("Docker is not supported on this host");
}
- if (isPodman() & !Platform.isRoot()) {
+ if (DockerTestUtils.isPodman() & !Platform.isRoot()) {
throw new SkippedException("test cannot be run under rootless podman configuration");
}
@@ -222,10 +222,4 @@ static File transferRecording(FlightRecorderMXBean bean, long streamId) throws E
}
}
- static boolean isPodman() {
- String[] parts = Container.ENGINE_COMMAND
- .toLowerCase()
- .split(File.pathSeparator);
- return "podman".equals(parts[parts.length - 1]);
- }
}
diff --git a/test/hotspot/jtreg/containers/docker/TestJcmd.java b/test/hotspot/jtreg/containers/docker/TestJcmd.java
index 4b604096b00..8c210544bb6 100644
--- a/test/hotspot/jtreg/containers/docker/TestJcmd.java
+++ b/test/hotspot/jtreg/containers/docker/TestJcmd.java
@@ -57,7 +57,7 @@ public class TestJcmd {
private static final String IMAGE_NAME = Common.imageName("jcmd");
private static final int TIME_TO_RUN_CONTAINER_PROCESS = (int) (10 * Utils.TIMEOUT_FACTOR); // seconds
private static final String CONTAINER_NAME = "test-container";
- private static final boolean IS_PODMAN = Container.ENGINE_COMMAND.contains("podman");
+ private static final boolean IS_PODMAN = DockerTestUtils.isPodman();
private static final String ROOT_UID = "0";
diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java
new file mode 100644
index 00000000000..68331f26766
--- /dev/null
+++ b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2025, IBM Corporation. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.Container;
+import jdk.test.lib.containers.docker.Common;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.containers.docker.ContainerRuntimeVersionTestUtils;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.internal.platform.Metrics;
+
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.util.ArrayList;
+
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
+
+/*
+ * @test
+ * @bug 8370966
+ * @requires os.family == "linux"
+ * @requires !vm.asan
+ * @modules java.base/jdk.internal.platform
+ * @library /test/lib
+ * @run main TestMemoryInvisibleParent
+ */
+public class TestMemoryInvisibleParent {
+ private static final String UNLIMITED = "-1";
+ private static final String imageName = Common.imageName("invisible-parent");
+
+ public static void main(String[] args) throws Exception {
+ Metrics metrics = Metrics.systemMetrics();
+ if (metrics == null) {
+ System.out.println("Cgroup not configured.");
+ return;
+ }
+ if (!DockerTestUtils.canTestDocker()) {
+ System.out.println("Unable to run docker tests.");
+ return;
+ }
+
+ ContainerRuntimeVersionTestUtils.checkContainerVersionSupported();
+
+ if (DockerTestUtils.isRootless()) {
+ throw new SkippedException("Test skipped in rootless mode");
+ }
+ if (!Platform.isRoot()) {
+ throw new SkippedException("Test should be run as root");
+ }
+ DockerTestUtils.buildJdkContainerImage(imageName);
+
+ if ("cgroupv1".equals(metrics.getProvider())) {
+ try {
+ testMemoryLimitHiddenParent("104857600", "104857600");
+ testMemoryLimitHiddenParent("209715200", "209715200");
+ } finally {
+ DockerTestUtils.removeDockerImage(imageName);
+ }
+ } else {
+ throw new SkippedException("cgroup v1 - only test! This is " + metrics.getProvider());
+ }
+ }
+
+ private static void testMemoryLimitHiddenParent(String valueToSet, String expectedValue)
+ throws Exception {
+
+ Common.logNewTestCase("Cgroup V1 hidden parent memory limit: " + valueToSet);
+
+ try {
+ String cgroupParent = setParentWithLimit(valueToSet);
+ DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version", "-Xlog:os+container=trace");
+ opts.appendTestJavaOptions = false;
+ if (DockerTestUtils.isPodman()) {
+ // Podman needs to run this test with engine option --cgroup-manager=cgroupfs
+ opts.addEngineOpts("--cgroup-manager", "cgroupfs");
+ }
+ opts.addDockerOpts("--cgroup-parent=/" + cgroupParent);
+ Common.run(opts)
+ .shouldContain("Hierarchical Memory Limit is: " + expectedValue);
+ } finally {
+ // Reset the parent memory limit to unlimited (-1)
+ setParentWithLimit(UNLIMITED);
+ }
+ }
+
+ private static String setParentWithLimit(String memLimit) throws Exception {
+ String cgroupParent = "hidden-parent-" + TestMemoryInvisibleParent.class.getSimpleName() + Runtime.version().feature();
+ Path sysFsMemory = Path.of("/", "sys", "fs", "cgroup", "memory");
+ Path cgroupParentPath = sysFsMemory.resolve(cgroupParent);
+ ProcessBuilder pb = new ProcessBuilder("mkdir", "-p", cgroupParentPath.toString());
+ OutputAnalyzer out = new OutputAnalyzer(pb.start())
+ .shouldHaveExitValue(0);
+ Path memoryLimitsFile = cgroupParentPath.resolve("memory.limit_in_bytes");
+ Files.writeString(memoryLimitsFile, memLimit);
+ System.out.println("Cgroup parent is: /" + cgroupParentPath.getFileName() +
+ " at " + sysFsMemory.toString());
+ return cgroupParent;
+ }
+
+}
diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
index bd1713e578c..3b901765ee9 100644
--- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
+++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
@@ -46,19 +46,6 @@
public class TestMemoryWithSubgroups {
private static final String imageName = Common.imageName("subgroup");
- static String getEngineInfo(String format) throws Exception {
- return DockerTestUtils.execute(Container.ENGINE_COMMAND, "info", "-f", format)
- .getStdout();
- }
-
- static boolean isRootless() throws Exception {
- // Docker and Podman have different INFO structures.
- // The node path for Podman is .Host.Security.Rootless, that also holds for
- // Podman emulating Docker CLI. The node path for Docker is .SecurityOptions.
- return (getEngineInfo("{{.Host.Security.Rootless}}").contains("true") ||
- getEngineInfo("{{.SecurityOptions}}").contains("name=rootless"));
- }
-
public static void main(String[] args) throws Exception {
Metrics metrics = Metrics.systemMetrics();
if (metrics == null) {
@@ -72,7 +59,7 @@ public static void main(String[] args) throws Exception {
ContainerRuntimeVersionTestUtils.checkContainerVersionSupported();
- if (isRootless()) {
+ if (DockerTestUtils.isRootless()) {
throw new SkippedException("Test skipped in rootless mode");
}
Common.prepareWhiteBox();
diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java
index 4da13067399..a1998cef344 100644
--- a/test/hotspot/jtreg/containers/docker/TestMisc.java
+++ b/test/hotspot/jtreg/containers/docker/TestMisc.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -111,9 +111,11 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception {
"CPU Shares",
"CPU Quota",
"CPU Period",
+ "CPU Usage",
"OSContainer::active_processor_count",
"Memory Limit",
"Memory Soft Limit",
+ "Memory Throttle Limit",
"Memory Usage",
"Maximum Memory Usage",
"memory_max_usage_in_bytes",
diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java
index 2e9c97110b2..62bd70dc61f 100644
--- a/test/hotspot/jtreg/containers/docker/TestPids.java
+++ b/test/hotspot/jtreg/containers/docker/TestPids.java
@@ -47,7 +47,7 @@
public class TestPids {
private static final String imageName = Common.imageName("pids");
- private static final boolean IS_PODMAN = Container.ENGINE_COMMAND.contains("podman");
+ private static final boolean IS_PODMAN = DockerTestUtils.isPodman();
private static final int UNLIMITED_PIDS_PODMAN = 0;
private static final int UNLIMITED_PIDS_DOCKER = -1;
diff --git a/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java b/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java
index 141ef7ba197..79b6d420df5 100644
--- a/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java
+++ b/test/hotspot/jtreg/gc/TestAlwaysPreTouchBehavior.java
@@ -133,13 +133,8 @@ public class TestAlwaysPreTouchBehavior {
//
public static void main(String [] args) {
- long rss = WhiteBox.getWhiteBox().rss();
- System.out.println("RSS: " + rss);
- long available = WhiteBox.getWhiteBox().hostAvailableMemory();
- System.out.println("Host available memory: " + available);
-
+ int maxIter = 20;
long heapSize = 256 * 1024 * 1024;
-
// On Linux, a JVM that runs with 256M pre-committed heap will use about 60MB (release JVM) RSS. Barring
// memory pressure that causes us to lose RSS, pretouching should increase RSS to >256MB. So there should be a
// clear distinction between non-pretouched and pretouched.
@@ -150,12 +145,28 @@ public static void main(String [] args) {
// on the side of disregarding true errors than to produce false positives (if pretouching is broken, at least
// some of the runs of this test will run on beefy enough machines and show the test as failed).
long requiredAvailable = 1024 * 1024 * 1024;
- if (rss == 0) {
- throw new SkippedException("cannot get RSS?");
- }
- if (available > requiredAvailable) {
- Asserts.assertGreaterThan(rss, minRequiredRss, "RSS of this process(" + rss + "b) should be bigger " +
- "than or equal to heap size(" + heapSize + "b) (available memory: " + available + "). On Linux Kernel < 4.14 RSS can be inaccurate");
+
+ // RSS values we get are sometimes somewhat delayed or inaccurate
+ for (int iter=0; iter < maxIter; iter++) {
+ long rss = WhiteBox.getWhiteBox().rss();
+ System.out.println("RSS: " + rss);
+ long available = WhiteBox.getWhiteBox().hostAvailableMemory();
+ System.out.println("Host available memory: " + available);
+
+ if (rss == 0) {
+ throw new SkippedException("cannot get RSS?");
+ }
+ if (available <= requiredAvailable) {
+ throw new SkippedException("Available memory on host " + available + " is too small, not larger than required available memory " + requiredAvailable);
+ }
+
+ if ((rss < minRequiredRss) && iter < maxIter-1) {
+ System.out.println("We got only an RSS value of " + rss + " but require " + minRequiredRss + ", let's retry!");
+ } else {
+ Asserts.assertGreaterThan(rss, minRequiredRss, "RSS of this process(" + rss + "b) should be bigger " +
+ "than or equal to heap size(" + heapSize + "b) (available memory: " + available + "). On Linux Kernel < 4.14 RSS can be inaccurate");
+ break;
+ }
}
}
}
diff --git a/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java b/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java
index 5fb46a87b51..7abded3673e 100644
--- a/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.java
+++ b/test/hotspot/jtreg/gc/TestObjectAlignmentCardSize.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
@@ -26,6 +26,7 @@
/* @test TestObjectAlignmentCardSize.java
* @summary Test to check correct handling of ObjectAlignmentInBytes and GCCardSizeInBytes combinations
* @requires vm.gc != "Z"
+ * @requires vm.bits == "64"
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @run driver gc.TestObjectAlignmentCardSize
diff --git a/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java b/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java
new file mode 100644
index 00000000000..8f1d541d385
--- /dev/null
+++ b/test/hotspot/jtreg/gc/TestUseGCOverheadLimit.java
@@ -0,0 +1,98 @@
+/*
+ * 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 gc;
+
+/*
+ * @test id=Parallel
+ * @requires vm.gc.Parallel & false
+ * @requires !vm.debug
+ * @summary Verifies that the UseGCOverheadLimit functionality works in Parallel GC.
+ * @library /test/lib
+ * @run driver gc.TestUseGCOverheadLimit Parallel
+ */
+
+/*
+ * @test id=G1
+ * @requires vm.gc.G1
+ * @requires !vm.debug
+ * @summary Verifies that the UseGCOverheadLimit functionality works in G1 GC.
+ * @library /test/lib
+ * @run driver gc.TestUseGCOverheadLimit G1
+ */
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestUseGCOverheadLimit {
+ public static void main(String args[]) throws Exception {
+ String[] parallelArgs = {
+ "-XX:+UseParallelGC",
+ "-XX:NewSize=122m",
+ "-XX:SurvivorRatio=99",
+ "-XX:GCHeapFreeLimit=10"
+ };
+ String[] g1Args = {
+ "-XX:+UseG1GC",
+ "-XX:GCHeapFreeLimit=5"
+ };
+
+ String[] selectedArgs = args[0].equals("G1") ? g1Args : parallelArgs;
+
+ final String[] commonArgs = {
+ "-XX:-UseCompactObjectHeaders", // Object sizes are calculated such that the heap is tight.
+ "-XX:ParallelGCThreads=1", // Make GCs take longer.
+ "-XX:+UseGCOverheadLimit",
+ "-Xlog:gc=debug",
+ "-XX:GCTimeLimit=80", // Ease the CPU requirement.
+ "-Xmx128m",
+ Allocating.class.getName()
+ };
+
+ String[] vmArgs = Stream.concat(Arrays.stream(selectedArgs), Arrays.stream(commonArgs)).toArray(String[]::new);
+ OutputAnalyzer output = ProcessTools.executeLimitedTestJava(vmArgs);
+ output.shouldNotHaveExitValue(0);
+
+ System.out.println(output.getStdout());
+
+ output.stdoutShouldContain("GC Overhead Limit exceeded too often (5).");
+ }
+
+ static class Allocating {
+ public static void main(String[] args) {
+ Object[] cache = new Object[1024 * 1024 * 2];
+
+ // Allocate random objects, keeping around data, causing garbage
+ // collections.
+ for (int i = 0; i < 1024* 1024 * 30; i++) {
+ Object[] obj = new Object[10];
+ cache[i % cache.length] = obj;
+ }
+
+ System.out.println(cache);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java
index 63c51c25149..b9e5629d875 100644
--- a/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java
@@ -27,7 +27,7 @@
* @test TestParallelGCErgo
* @bug 8272364
* @requires vm.gc.Parallel
- * @requires vm.opt.UseLargePages == null | !vm.opt.UseLargePages
+ * @requires !vm.opt.final.UseLargePages
* @summary Verify ParallelGC minimum young and old ergonomics are setup correctly
* @modules java.base/jdk.internal.misc
* @library /test/lib
diff --git a/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java
index a4fadc185d2..e36ccace9dc 100644
--- a/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java
+++ b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java
@@ -53,9 +53,9 @@
import java.util.regex.Pattern;
import jdk.test.lib.Asserts;
+import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
-import static jdk.test.lib.Asserts.*;
import jdk.test.whitebox.WhiteBox;
public class TestCodeCacheUnloadDuringConcCycle {
@@ -70,9 +70,10 @@ private static OutputAnalyzer runTest(String concPhase) throws Exception {
"-Xbootclasspath/a:.",
"-Xlog:gc=trace,codecache",
"-XX:+WhiteBoxAPI",
- "-XX:ReservedCodeCacheSize=8M",
+ "-XX:ReservedCodeCacheSize=" + (Platform.is32bit() ? "4M" : "8M"),
"-XX:StartAggressiveSweepingAt=50",
"-XX:CompileCommand=compileonly,gc.g1.SomeClass::*",
+ "-XX:CompileCommand=compileonly,gc.g1.Foo*::*",
TestCodeCacheUnloadDuringConcCycleRunner.class.getName(),
concPhase);
return output;
diff --git a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java
index a3dded8d09a..7ca9c7f46d6 100644
--- a/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java
+++ b/test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java
@@ -23,105 +23,175 @@
*
*/
-/*
- * @test id=passive
+/**
+ * @test id=satb-adaptive
* @requires vm.gc.Shenandoah
* @library /test/lib
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000
+ * -XX:ShenandoahGCMode=satb
* -XX:+ShenandoahDegeneratedGC
- * -Dtarget=10000
+ * -XX:ShenandoahGCHeuristics=adaptive
* TestDynamicSoftMaxHeapSize
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
- * -XX:-ShenandoahDegeneratedGC
- * -Dtarget=10000
- * TestDynamicSoftMaxHeapSize
*/
-/*
- * @test id=aggressive
+/**
+ * @test id=satb-aggressive
* @requires vm.gc.Shenandoah
* @library /test/lib
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
- * -Dtarget=1000
+ * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000
+ * -XX:ShenandoahGCMode=satb
+ * -XX:+ShenandoahDegeneratedGC
+ * -XX:ShenandoahGCHeuristics=aggressive
* TestDynamicSoftMaxHeapSize
+ *
*/
-/*
- * @test id=adaptive
+/**
+ * @test id=satb-compact
* @requires vm.gc.Shenandoah
* @library /test/lib
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
- * -Dtarget=10000
+ * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000
+ * -XX:ShenandoahGCMode=satb
+ * -XX:+ShenandoahDegeneratedGC
+ * -XX:ShenandoahGCHeuristics=compact
* TestDynamicSoftMaxHeapSize
+ *
*/
-/*
- * @test id=generational
+/**
+ * @test id=satb-static
* @requires vm.gc.Shenandoah
* @library /test/lib
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive -XX:ShenandoahGCMode=generational
- * -Dtarget=10000
+ * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000
+ * -XX:ShenandoahGCMode=satb
+ * -XX:+ShenandoahDegeneratedGC
+ * -XX:ShenandoahGCHeuristics=static
* TestDynamicSoftMaxHeapSize
+ *
*/
-/*
- * @test id=static
+/**
+ * @test id=passive
* @requires vm.gc.Shenandoah
* @library /test/lib
*
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ * -XX:+ShenandoahDegeneratedGC
+ * -Dtarget=10000
+ * TestDynamicSoftMaxHeapSize
+ *
+ * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ * -XX:-ShenandoahDegeneratedGC
* -Dtarget=10000
* TestDynamicSoftMaxHeapSize
*/
-/*
- * @test id=compact
+/**
+ * @test id=generational
* @requires vm.gc.Shenandoah
* @library /test/lib
*
- * @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
- * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
- * -Dtarget=1000
- * TestDynamicSoftMaxHeapSize
+ * @run main/othervm -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000
+ * -XX:ShenandoahGCMode=generational
+ * -XX:ShenandoahGCHeuristics=adaptive
+ * TestDynamicSoftMaxHeapSize
+ *
*/
-import java.util.Random;
+/**
+ * @test id=generational-softMaxHeapSizeValidation
+ * @requires vm.gc.Shenandoah
+ * @library /test/lib
+ *
+ * @run main/othervm -DvalidateSoftMaxHeap=true
+ * TestDynamicSoftMaxHeapSize
+ * -Xms100m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ * -XX:+UseShenandoahGC -Xlog:gc=info -Dtarget=10000 -DverifySoftMaxHeapValue=true
+ * -XX:ShenandoahGCMode=generational
+ * -XX:ShenandoahGCHeuristics=adaptive
+ */
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.dcmd.PidJcmdExecutor;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
public class TestDynamicSoftMaxHeapSize {
+ static final int K = 1024;
+ static final int XMS_MB = 100;
+ static final int XMX_MB = 512;
+
+ public static void main(String[] args) throws Exception {
+ if ("true".equals(System.getProperty("validateSoftMaxHeap"))) {
+ List flagArgs = new ArrayList<>(Arrays.asList(args));
- static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation
- static final long STRIDE = 10_000_000;
+ int softMaxInMb = Utils.getRandomInstance().nextInt(XMS_MB, XMX_MB);
+ flagArgs.add("-DsoftMaxCapacity=" + softMaxInMb * K * K);
+ flagArgs.add("-Dtest.jdk=" + System.getProperty("test.jdk"));
+ flagArgs.add("-Dcompile.jdk=" + System.getProperty("compile.jdk"));
- static volatile Object sink;
+ flagArgs.add(SoftMaxWithExpectationTest.class.getName());
- public static void main(String[] args) throws Exception {
- long count = TARGET_MB * 1024 * 1024 / 16;
- Random r = Utils.getRandomInstance();
- PidJcmdExecutor jcmd = new PidJcmdExecutor();
-
- for (long c = 0; c < count; c += STRIDE) {
- // Sizes specifically include heaps below Xms and above Xmx to test saturation code.
- jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true);
- for (long s = 0; s < STRIDE; s++) {
- sink = new Object();
+ ProcessBuilder genShenPbValidateFlag = ProcessTools.createLimitedTestJavaProcessBuilder(flagArgs);
+ OutputAnalyzer output = new OutputAnalyzer(genShenPbValidateFlag.start());
+ output.shouldHaveExitValue(0);
+ output.shouldContain(String.format("Soft Max Heap Size: %dM -> %dM", XMX_MB, softMaxInMb)); // By default, the soft max heap size is Xmx
+ } else {
+ SoftMaxSetFlagOnlyTest.test();
+ }
+ }
+
+ public static class SoftMaxSetFlagOnlyTest {
+ static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation
+ static final long STRIDE = 10_000_000;
+
+ static volatile Object sink;
+
+ public static void test() throws Exception {
+ long count = TARGET_MB * 1024 * 1024 / 16;
+ Random r = Utils.getRandomInstance();
+ PidJcmdExecutor jcmd = new PidJcmdExecutor();
+
+ for (long c = 0; c < count; c += STRIDE) {
+ // Sizes specifically include heaps below Xms and above Xmx to test saturation code.
+ jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true);
+ for (long s = 0; s < STRIDE; s++) {
+ sink = new Object();
+ }
+ Thread.sleep(1);
}
- Thread.sleep(1);
}
}
+ public static class SoftMaxWithExpectationTest {
+ static final long TOTAL = 100_000_000;
+
+ static volatile Object sink;
+
+ public static void main(String[] args) throws Exception {
+ int expectedSoftMaxHeapSize = Integer.getInteger("softMaxCapacity", 0);
+ PidJcmdExecutor jcmd = new PidJcmdExecutor();
+ jcmd.execute("VM.set_flag SoftMaxHeapSize " + expectedSoftMaxHeapSize, false);
+
+ for (long s = 0; s < TOTAL; s++) {
+ sink = new Object();
+ }
+ }
+ }
}
diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java
index 2e98c72ee17..0775e5baadd 100644
--- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java
+++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestClone.java
@@ -357,6 +357,7 @@
* -XX:TieredStopAtLevel=4
* TestClone
*/
+
public class TestClone {
public static void main(String[] args) throws Exception {
diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java
index 840ceffc4fe..a72baddc5dc 100644
--- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java
+++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java
@@ -25,6 +25,7 @@
/*
* @test id=generational
* @summary Test that growth of old-gen triggers old-gen marking
+ * @key intermittent
* @requires vm.gc.Shenandoah
* @library /test/lib
* @run driver TestOldGrowthTriggers
diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java
index 180dc539795..3fee5ab131f 100644
--- a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java
+++ b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -29,16 +29,25 @@
* cause, even if we can't create the ExceptionInInitializerError
* @comment This test could easily be perturbed so don't allow flag settings.
* @requires vm.flagless
+ * @library /test/lib
* @comment Run with the smallest stack possible to limit the execution time.
* This is the smallest stack that is supported by all platforms.
- * @run main/othervm -Xss384K -Xint TestStackOverflowDuringInit
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestStackOverflowDuringInit
*/
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.whitebox.WhiteBox;
public class TestStackOverflowDuringInit {
+ static String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache";
+ static String cause = "Caused by: java.lang.StackOverflowError";
+
// The setup for this is somewhat intricate. We need to trigger a
// StackOverflowError during execution of the static initializer
// for a class, but we need there to be insufficient stack left
@@ -88,34 +97,47 @@ static void recurse() {
}
}
- public static void main(String[] args) throws Exception {
- String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache";
- String cause = "Caused by: java.lang.StackOverflowError";
+ static class Launcher {
+ public static void main(String[] args) throws Exception {
- // Pre-load, but not initialize, LongCache, else we will
- // hit SOE during class loading.
- System.out.println("Pre-loading ...");
- Class> c = Class.forName("TestStackOverflowDuringInit$LongCache",
- false,
- TestStackOverflowDuringInit.class.getClassLoader());
- try {
- recurse();
- } catch (Throwable ex) {
- // ex.printStackTrace();
- verify_stack(ex, expected, cause);
+ // Pre-load, but not initialize, LongCache, else we will
+ // hit SOE during class loading.
+ System.out.println("Pre-loading ...");
+ Class> c = Class.forName("TestStackOverflowDuringInit$LongCache",
+ false,
+ TestStackOverflowDuringInit.class.getClassLoader());
+ try {
+ recurse();
+ } catch (Throwable ex) {
+ // ex.printStackTrace();
+ verify_stack(ex, expected, cause);
+ }
}
- }
- private static void verify_stack(Throwable e, String expected, String cause) throws Exception {
- ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
- try (PrintStream printStream = new PrintStream(byteOS)) {
- e.printStackTrace(printStream);
- }
- String stackTrace = byteOS.toString("ASCII");
- System.out.println(stackTrace);
- if (!stackTrace.contains(expected) ||
- (cause != null && !stackTrace.contains(cause))) {
- throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace");
+ private static void verify_stack(Throwable e, String expected, String cause) throws Exception {
+ ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
+ try (PrintStream printStream = new PrintStream(byteOS)) {
+ e.printStackTrace(printStream);
+ }
+ String stackTrace = byteOS.toString("ASCII");
+ System.out.println(stackTrace);
+ if (!stackTrace.contains(expected) ||
+ (cause != null && !stackTrace.contains(cause))) {
+ throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace");
+ }
}
}
+
+ public static void main(String[] args) throws Exception {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ long minimumJavaStackSize = wb.getMinimumJavaStackSize();
+ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
+ "-Xss" + Long.toString(minimumJavaStackSize), "-Xint",
+ Launcher.class.getName());
+
+ OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
+ analyzer.shouldHaveExitValue(0);
+ analyzer.shouldContain(expected);
+ analyzer.shouldContain(cause);
+ }
}
diff --git a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
index 78a508343d6..d87ca25fc3c 100644
--- a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
+++ b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
@@ -116,7 +116,7 @@ static JVMOption createVMOption(String type, String name) {
default:
throw new Error("Expected only \"int\", \"intx\", \"size_t\", "
+ "\"uint\", \"uintx\", \"uint64_t\", or \"double\" "
- + "option types! Got " + type + " type!");
+ + "option types! Got " + type + " type for option " + name + "!");
}
return parameter;
diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java
index 2b9393e3d35..5e535bab626 100644
--- a/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/PrintVMInfoAtExitTest.java
@@ -27,14 +27,18 @@
* @test
* @summary Test PrintVMInfoAtExit
* @library /test/lib
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @modules java.base/jdk.internal.misc
* @requires vm.flagless
* @requires vm.bits == "64"
- * @run driver PrintVMInfoAtExitTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI PrintVMInfoAtExitTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jdk.test.whitebox.WhiteBox;
+
public class PrintVMInfoAtExitTest {
@@ -53,7 +57,14 @@ public static void main(String[] args) throws Exception {
output_detail.shouldContain("-- S U M M A R Y --");
output_detail.shouldContain("Command Line: -Xmx64M -Xms64M -XX:-CreateCoredumpOnCrash -XX:+UnlockDiagnosticVMOptions -XX:+PrintVMInfoAtExit -XX:NativeMemoryTracking=summary -XX:CompressedClassSpaceSize=256m");
output_detail.shouldContain("Native Memory Tracking:");
- output_detail.shouldContain("Java Heap (reserved=65536KB, committed=65536KB)");
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ if (wb.isAsanEnabled()) {
+ // the reserved value can be influenced by asan
+ output_detail.shouldContain("Java Heap (reserved=");
+ output_detail.shouldContain(", committed=65536KB)");
+ } else {
+ output_detail.shouldContain("Java Heap (reserved=65536KB, committed=65536KB)");
+ }
}
}
diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
index 0be39d22ebe..26d1f726feb 100644
--- a/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, 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
@@ -72,8 +72,8 @@ public static void main(String[] args) throws Exception {
#
# JRE version: OpenJDK Runtime Environment (9.0) (build 1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00)
# Java VM: OpenJDK 64-Bit Server VM (1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00, mixed mode, tiered, compressed oops, serial gc, linux-amd64)
- # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %P" (or dumping to
- /home/cheleswer/Desktop/core.6212)
+ # Core dump will be written. Default location: Determined by the following:
+ "/usr/share/apport/apport %p %s %c %P" (alternatively, falling back to /home/cheleswer/Desktop/core.6212)
#
# An error report file with more information is saved as:
# /home/cheleswer/Desktop/hs_err_pid6212.log
diff --git a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java
index 398d6b523ad..28af0692721 100644
--- a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java
+++ b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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,11 +26,14 @@
* @bug 8133747 8218458
* @summary Running with NMT detail should produce expected stack traces.
* @library /test/lib
+ * @library /
* @modules java.base/jdk.internal.misc
* java.management
* @requires vm.debug
+ * @build jdk.test.whitebox.WhiteBox
* @compile ../modules/CompilerUtils.java
- * @run driver CheckForProperDetailStackTrace
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI CheckForProperDetailStackTrace
*/
import jdk.test.lib.Platform;
@@ -40,6 +43,7 @@
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import jdk.test.whitebox.WhiteBox;
/**
* We are checking for details that should be seen with NMT detail enabled.
@@ -59,7 +63,10 @@ public class CheckForProperDetailStackTrace {
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
private static final Path MODS_DIR = Paths.get(TEST_CLASSES, "mods");
- private static final boolean expectSourceInformation = Platform.isLinux() || Platform.isWindows();
+ // Windows has source information only in full pdbs, not in stripped pdbs
+ private static boolean expectSourceInformation = Platform.isLinux() || Platform.isWindows();
+
+ static WhiteBox wb = WhiteBox.getWhiteBox();
/* The stack trace we look for by default. Note that :: has been replaced by .*
to make sure it matches even if the symbol is not unmangled.
@@ -138,6 +145,10 @@ public static void main(String args[]) throws Exception {
throw new RuntimeException("Expected stack trace missing from output");
}
+ if (wb.hasExternalSymbolsStripped()) {
+ expectSourceInformation = false;
+ }
+
System.out.println("Looking for source information:");
if (expectSourceInformation) {
if (!stackTraceMatches(".*moduleEntry.cpp.*", output)) {
diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java
index 57f2302db30..a7561c7792e 100644
--- a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java
+++ b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -35,13 +35,14 @@
public class CommandLineDetail {
- public static void main(String args[]) throws Exception {
-
- ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
- "-XX:NativeMemoryTracking=detail",
- "-version");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldNotContain("error");
- output.shouldHaveExitValue(0);
- }
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
+ "-Xlog:nmt=warning",
+ "-XX:NativeMemoryTracking=detail",
+ "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("NMT initialization failed");
+ output.shouldNotContain("Could not create the Java Virtual Machine.");
+ output.shouldHaveExitValue(0);
+ }
}
diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java
index 02b37a40ef4..381fe3eba34 100644
--- a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java
+++ b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -35,13 +35,14 @@
public class CommandLineSummary {
- public static void main(String args[]) throws Exception {
-
- ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
- "-XX:NativeMemoryTracking=summary",
- "-version");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldNotContain("error");
- output.shouldHaveExitValue(0);
- }
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
+ "-Xlog:nmt=warning",
+ "-XX:NativeMemoryTracking=summary",
+ "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("NMT initialization failed");
+ output.shouldNotContain("Could not create the Java Virtual Machine.");
+ output.shouldHaveExitValue(0);
+ }
}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java
index 0c747168945..6b7a4f68bbf 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java
@@ -28,8 +28,6 @@
* @summary CDS cannot archive lambda proxy with useImplMethodHandle
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* @build pkg1.BaseWithProtectedMethod
* @build pkg2.Child
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java b/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java
index 1ad28f99408..9e6cb58bb7f 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/SignedJar.java
@@ -50,8 +50,8 @@ public static void main(String[] args) throws Exception {
String skipMsg = "Skipping Hello: Signed JAR";
String lambdaInArchive = "klasses.*=.*app.*Hello[$][$]Lambda.*hidden";
- String loadFromJar = ".class,load. Hello source: file:.*signed_hello.jar";
- String lambdaLoadFromHello = ".class.load. Hello[$][$]Lambda.*/0x.*source.*Hello";
+ String loadFromJar = ".class,load\s*. Hello source: file:.*signed_hello.jar";
+ String lambdaLoadFromHello = ".class.load\s*. Hello[$][$]Lambda.*/0x.*source.*Hello";
for (String mainArg : mainArgs) {
output = TestCommon.dump(signedJar, TestCommon.list(mainClass),
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java
index 4ed2ce4446d..be7e69b076c 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java
@@ -121,34 +121,23 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use
out.shouldNotContain(errMsg);
out.shouldHaveExitValue(0);
- int n = 2;
if (!dumpWithParallel && execWithParallel) {
// We dumped with G1, so we have an archived heap. At exec time, try to load them into
// a small ParallelGC heap that may be too small.
- String[] sizes = {
- "4m", // usually this will success load the archived heap
- "2m", // usually this will fail to load the archived heap, but app can launch
- // or fail with "GC triggered before VM initialization completed"
- "1m" // usually this will cause VM launch to fail with "Too small maximum heap"
- };
- for (String sz : sizes) {
- String xmx = "-Xmx" + sz;
- System.out.println("=======\n" + n + ". Exec with " + execGC + " " + xmx);
- out = TestCommon.exec(helloJar,
- execGC,
- small1,
- small2,
- xmx,
- coops,
- "-Xlog:cds",
- "Hello");
- if (out.getExitValue() == 0) {
- out.shouldContain(HELLO);
- out.shouldNotContain(errMsg);
- } else {
- out.shouldNotHaveFatalError();
- }
- n++;
+ System.out.println("2. Exec with " + execGC);
+ out = TestCommon.exec(helloJar,
+ execGC,
+ small1,
+ small2,
+ "-Xmx4m",
+ coops,
+ "-Xlog:cds",
+ "Hello");
+ if (out.getExitValue() == 0) {
+ out.shouldContain(HELLO);
+ out.shouldNotContain(errMsg);
+ } else {
+ out.shouldNotHaveFatalError();
}
}
}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java
index ae00477e67b..9461957ef2c 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTCacheSupportForCustomLoaders.java
@@ -27,8 +27,6 @@
* @summary Test AOT cache support for array classes in custom class loaders.
* @bug 8353298 8356838
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* @build ReturnIntegerAsString
* @build AOTCacheSupportForCustomLoaders
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java
new file mode 100644
index 00000000000..1f4111ecfb1
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/CloseSystemOut.java
@@ -0,0 +1,82 @@
+/*
+ * 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
+ * @summary AOT configuration should not be corrupted even if the app closes System.out in the training run
+ * @bug 8371944
+ * @library /test/jdk/lib/testlibrary /test/lib
+ * @build CloseSystemOut
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar CloseSystemOutApp
+ * @run driver CloseSystemOut
+ */
+
+import java.io.PrintWriter;
+import jdk.test.lib.cds.CDSAppTester;
+import jdk.test.lib.helpers.ClassFileInstaller;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class CloseSystemOut {
+ static final String appJar = ClassFileInstaller.getJarPath("app.jar");
+ static final String mainClass = "CloseSystemOutApp";
+
+ public static void main(String[] args) throws Exception {
+ Tester tester = new Tester();
+ tester.run(new String[] {"AOT", "--two-step-training"} );
+ }
+
+ static class Tester extends CDSAppTester {
+ public Tester() {
+ super(mainClass);
+ }
+
+ @Override
+ public String classpath(RunMode runMode) {
+ return appJar;
+ }
+
+ @Override
+ public String[] appCommandLine(RunMode runMode) {
+ return new String[] {mainClass};
+ }
+
+ @Override
+ public void checkExecution(OutputAnalyzer out, RunMode runMode) {
+ if (runMode != RunMode.ASSEMBLY) {
+ out.shouldContain("Hello Confused World");
+ }
+ }
+ }
+}
+
+class CloseSystemOutApp {
+ public static void main(String args[]) {
+ // Naive code that ends up closing System.out/err when we
+ // leave the "try" block
+ try (var err = new PrintWriter(System.err);
+ var out = new PrintWriter(System.out)) {
+ out.println("Hello Confused World");
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java
index 412ed8b2585..f50a2d1f905 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ExcludedClasses.java
@@ -26,8 +26,6 @@
* @test
* @summary Test how various AOT optimizations handle classes that are excluded from the AOT cache.
* @requires vm.cds.write.archived.java.heap
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib
* /test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes
* @build ExcludedClasses CustyWithLoop
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java
index 007e51004ec..f3326ac1ed6 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HelloAOTCache.java
@@ -27,8 +27,6 @@
* @test
* @summary Sanity test for AOTCache
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build HelloAOTCache
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloAOTCacheApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java
new file mode 100644
index 00000000000..58c2cb42681
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JNIDefineClass.java
@@ -0,0 +1,138 @@
+/*
+ * 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
+ * @summary classes defined with JNI DefineClass should be excluded from the AOT config file and AOT cache.
+ * @bug 8368182
+ * @requires vm.cds
+ * @requires vm.cds.supports.aot.class.linking
+ * @library /test/lib
+ * @build JNIDefineClass
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
+ * JNIDefineClassApp ExcludedDummy ExcludedDummy2
+ * @run main/native JNIDefineClass
+ */
+
+import java.io.InputStream;
+import jdk.test.lib.cds.CDSAppTester;
+import jdk.test.lib.helpers.ClassFileInstaller;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class JNIDefineClass {
+ static final String appJar = ClassFileInstaller.getJarPath("app.jar");
+ static final String mainClass = "JNIDefineClassApp";
+
+ public static void main(String[] args) throws Exception {
+ Tester tester = new Tester();
+ tester.run(new String[] {"AOT", "--two-step-training"} );
+ }
+
+ static class Tester extends CDSAppTester {
+ public Tester() {
+ super(mainClass);
+ }
+
+ @Override
+ public String classpath(RunMode runMode) {
+ return appJar;
+ }
+
+ @Override
+ public String[] vmArgs(RunMode runMode) {
+ return new String[] {
+ "--enable-native-access=ALL-UNNAMED",
+ "-Xlog:aot,aot+class=debug",
+ "-Djava.library.path=" + System.getProperty("java.library.path"),
+ };
+ }
+
+ @Override
+ public String[] appCommandLine(RunMode runMode) {
+ return new String[] {mainClass};
+ }
+
+ @Override
+ public void checkExecution(OutputAnalyzer out, RunMode runMode) {
+ if (runMode.isApplicationExecuted()) {
+ out.shouldContain("@@loader = null");
+ out.shouldContain("@@name = ExcludedDummy");
+
+ out.shouldMatch("@@loader2 = .*AppClassLoader");
+ out.shouldContain("@@name2 = ExcludedDummy2");
+ }
+ if (runMode == RunMode.TRAINING) {
+ out.shouldContain("Skipping ExcludedDummy: Unsupported location");
+ }
+
+ // Must not have a log like this
+ /// [0.378s][debug ][aot,class] klasses[ 65] = 0x0000000800160490 boot ExcludedDummy
+ /// [0.378s][debug ][aot,class] klasses[ 66] = 0x0000000800160490 app ExcludedDummy2
+ out.shouldNotContain("aot,class.* klasses.*ExcludedDummy");
+ out.shouldNotContain("aot,class.* klasses.*ExcludedDummy2");
+ }
+ }
+}
+
+class JNIDefineClassApp {
+
+ static native Class> nativeDefineClass(String name, ClassLoader ldr, byte[] class_bytes);
+
+ static {
+ System.loadLibrary("JNIDefineClassApp");
+ }
+
+ public static void main(java.lang.String[] unused) throws Exception {
+ ClassLoader appLoader = JNIDefineClassApp.class.getClassLoader();
+
+ try (InputStream in = appLoader.getResourceAsStream("ExcludedDummy.class")) {
+ byte[] b = in.readAllBytes();
+ System.out.println(b.length);
+ Class> c = nativeDefineClass("ExcludedDummy", null, b);
+ System.out.println("@@loader = " + c.getClassLoader());
+ System.out.println("@@name = " + c.getName());
+ }
+
+ try (InputStream in = appLoader.getResourceAsStream("ExcludedDummy2.class")) {
+ byte[] b = in.readAllBytes();
+ System.out.println(b.length);
+ Class> c = nativeDefineClass("ExcludedDummy2", appLoader, b);
+ System.out.println("@@loader2 = " + c.getClassLoader());
+ System.out.println("@@name2 = " + c.getName());
+ }
+
+ System.out.println("TEST PASSED");
+ }
+}
+
+// This class is loaded into the bootstrap loader using JNI DefineClass() with a null code source,
+// so it should be excluded from the AOT configuration (and hence excluded from AOT cache)
+class ExcludedDummy {
+
+}
+
+// This class is loaded into the app loader using JNI DefineClass() with a null code source,
+// so it should be excluded from the AOT configuration (and hence excluded from AOT cache)
+class ExcludedDummy2 {
+
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
index 7965be8d00a..070f6df9834 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/JavaAgent.java
@@ -28,8 +28,6 @@
* @summary -javaagent should be allowed in AOT workflow. However, classes transformed/redefined by agents will not
* be cached.
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @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
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java
index abbdd3551b7..c558d293b2a 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/ManagementAgent.java
@@ -28,8 +28,6 @@
* @bug 8352187
* @summary ManagementAgent will not be started during AOT cache creation.
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build HelloAOTCache
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloAOTCacheApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java
index 0fff74236f1..014524afde6 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/PackageInfoClass.java
@@ -27,8 +27,6 @@
* @summary AOT cache handling for package-info class loaded by jdk/internal/loader/ClassLoaders$BootClassLoader
* @bug 8354558
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/jdk/java/lang/Package/bootclasspath/boot
* @build PackageInfoClass foo.Foo foo.MyAnnotation foo.package-info
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar foo.Foo foo.package-info foo.MyAnnotation
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java
index 89aa9e441a4..e9d9c70a358 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/SpecialCacheNames.java
@@ -27,8 +27,6 @@
* @summary Use special characters in the name of the cache file specified by -XX:AOTCacheOutput
* Make sure these characters are passed to the child JVM process that assembles the cache.
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build SpecialCacheNames
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java
index 18caa08c117..50b47e4424d 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java
@@ -26,8 +26,6 @@
* @test
* @summary Sanity test for AOTCache
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build VerifierFailOver_Helper
* @build VerifierFailOver
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c
new file mode 100644
index 00000000000..ec3ed3bc8f6
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/libJNIDefineClassApp.c
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include
+
+JNIEXPORT jclass JNICALL
+Java_JNIDefineClassApp_nativeDefineClass(JNIEnv* env, jclass clazz /*unused*/,
+ jstring className, jobject classLoader, jbyteArray bytecode) {
+ const char* classNameChar = (*env)->GetStringUTFChars(env, className, NULL);
+ jbyte* arrayContent = (*env)->GetByteArrayElements(env, bytecode, NULL);
+ jsize bytecodeLength = (*env)->GetArrayLength(env, bytecode);
+ jclass returnValue = (*env)->DefineClass(env, classNameChar, classLoader, arrayContent, bytecodeLength);
+ (*env)->ReleaseByteArrayElements(env, bytecode, arrayContent, JNI_ABORT);
+ (*env)->ReleaseStringUTFChars(env, className, classNameChar);
+ return returnValue;
+}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java
index 96f08004fb2..a7c7362b845 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTCacheWithZGC.java
@@ -28,8 +28,6 @@
* @bug 8352775
* @requires vm.cds
* @requires vm.gc.Z
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build AOTCacheWithZGC
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTCacheWithZGCApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java
index 63be2038907..f82cf2737fb 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AOTLoaderConstraintsTest.java
@@ -26,8 +26,6 @@
* @test Make sure loader constraints are passed from AOT preimage to final image.
* @bug 8348426
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib
* @build AOTLoaderConstraintsTest BootClass
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar BootClass
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java
index 2a63a4837c2..fc3e945cf9d 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddExports.java
@@ -28,8 +28,6 @@
* @bug 8352437
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @run driver AddExports
*/
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java
index 5ae8c4a6bb8..d3626d30c7e 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddOpens.java
@@ -26,8 +26,6 @@
* @test
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @run driver AddOpens
* @summary sanity test the --add-opens option
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java
index c1dbc602755..5c9364aa079 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/AddReads.java
@@ -27,8 +27,6 @@
* @bug 8354083
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @run driver AddReads
* @summary sanity test the --add-reads option
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
index 21e3e48e38e..0f7707edae3 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java
@@ -29,8 +29,6 @@
/*
* @test id=static
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @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
@@ -45,8 +43,6 @@
/*
* @test id=dynamic
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @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
@@ -61,8 +57,6 @@
/*
* @test id=aot
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* @build jdk.test.whitebox.WhiteBox InitiatingLoaderTester BadOldClassA BadOldClassB
* @build BulkLoaderTest SimpleCusty
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java
index 1ffc904963a..5da2e2754e8 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java
@@ -26,8 +26,6 @@
* @test Do not cache classes that are loaded from a fake location.
* @bug 8352001
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib
* @build FakeCodeLocation
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar FakeCodeLocationApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java
index dcb1c59c09f..0ee59bf5afd 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/GeneratedInternedString.java
@@ -28,8 +28,6 @@
* @requires vm.cds.write.archived.java.heap
* @requires vm.cds.supports.aot.class.linking
* @requires vm.debug
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @build GeneratedInternedString
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar GeneratedInternedStringApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java
index 9ed2524bff1..c91e999c40f 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/LambdaInExcludedClass.java
@@ -27,8 +27,6 @@
* @bug 8349888
* @requires vm.cds.supports.aot.class.linking
* @requires vm.gc.Epsilon
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib
* @build LambdaInExcludedClass
* @run driver jdk.test.lib.helpers.ClassFileInstaller LambdaInExcludedClassApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java
index f7a26a39db1..972dc287af5 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/MethodHandleTest.java
@@ -27,8 +27,6 @@
* @requires vm.cds.write.archived.java.heap
* @requires vm.cds.supports.aot.class.linking
* @requires vm.debug
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @build MethodHandleTest
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar mh.jar
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java
index ba21f5f98fb..17ff399d23c 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/NonFinalStaticWithInitVal.java
@@ -27,8 +27,6 @@
* @summary Handling of non-final static string that has an initial value
* @bug 8356125
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build NonFinalStaticWithInitVal_Helper
* @build NonFinalStaticWithInitVal
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java
index 3786c294791..81bf28010b1 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/StringConcatStress.java
@@ -34,8 +34,6 @@
/*
* @test id=aot
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build StringConcatStress
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar StringConcatStressApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java
index f88af3caed5..118b4c6af1d 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TestSetupAOTTest.java
@@ -28,8 +28,6 @@
* is used for running HotSpot tests in the "AOT mode"
* (E.g., make test JTREG=AOT_JDK=true TEST=open/test/hotspot/jtreg/runtime/invokedynamic)
* @requires vm.cds
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/setup_aot
* @build TestSetupAOTTest JavacBenchApp TestSetupAOT
* @run driver jdk.test.lib.helpers.ClassFileInstaller
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java
index fd896fd6958..df466151f98 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/TrainingRun.java
@@ -27,8 +27,6 @@
* @summary -XX:AOTMode=record should not interfere with app execution: (1) thread creation; (2) exit code
* @bug 8351327
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib
* @build TrainingRun
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java
index ae5cd5b3429..3b33d63b0d2 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/WeakReferenceTest.java
@@ -27,8 +27,6 @@
* @requires vm.cds.write.archived.java.heap
* @requires vm.cds.supports.aot.class.linking
* @requires vm.debug
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @build WeakReferenceTest
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar weakref.jar
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java
index e2285a59600..fe9c7e7bbb7 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotProfile/AOTProfileFlags.java
@@ -26,8 +26,6 @@
* @test
* @summary Sanity test of combinations of the diagnostic flags [+-]AOTRecordTraining and [+-]AOTReplayTraining
* @requires vm.cds
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @requires vm.cds.supports.aot.class.linking
* @requires vm.flagless
* @library /test/lib /test/setup_aot /test/hotspot/jtreg/runtime/cds/appcds/test-classes
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java
index 819db99a549..fed56937f2f 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java
@@ -28,8 +28,6 @@
* @summary Test for the -XX:ArchiveHeapTestClass flag
* @requires vm.debug == true & vm.cds.write.archived.java.heap
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @modules java.logging
* @library /test/jdk/lib/testlibrary /test/lib
* /test/hotspot/jtreg/runtime/cds/appcds
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java
index ba7c0def86a..1061207f764 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesAsCollectorTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java
index 3f5008ca8c3..3349d146e10 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesCastFailureTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java
index 70f02b9a3d7..bba3f367505 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesGeneralTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java
index 7de76f5e99a..9ce57a9c66b 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesInvokersTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java
index 1e4bfebce9d..8f75eff0dc7 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesPermuteArgumentsTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java
index 19755121282..8b431232825 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java
@@ -28,8 +28,6 @@
* @summary Run the MethodHandlesSpreadArgumentsTest.java test in CDSAppTester::AOT workflow.
* @requires vm.cds & vm.compMode != "Xcomp"
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java
index e187f408fb4..ecfaa265923 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java
@@ -28,8 +28,6 @@
* @bug 8340836
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/
* @build AOTLinkedLambdas
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java
index e262c55beea..4586b94b519 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java
@@ -28,8 +28,6 @@
* @bug 8343245
* @requires vm.cds
* @requires vm.cds.supports.aot.class.linking
- * @comment work around JDK-8345635
- * @requires !vm.jvmci.enabled
* @library /test/lib
* @build AOTLinkedVarHandles
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java
index 615aa1c7e7c..ed8e582b213 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/InternSharedString.java
@@ -27,8 +27,6 @@
* @summary Test shared strings together with string intern operation
* @requires vm.cds.write.archived.java.heap
* @requires vm.gc == null
- * @comment CDS archive heap mapping is not supported with large pages
- * @requires vm.opt.UseLargePages == null | !vm.opt.UseLargePages
* @library /test/hotspot/jtreg/runtime/cds/appcds /test/lib
* @compile InternStringTest.java
* @build jdk.test.whitebox.WhiteBox
diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java
index e0491b4b89f..0684ad1aacc 100644
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE78_A.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 by SAP AG, Walldorf, Germany.
+ * Copyright (c) 2018, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java
index 373ee584679..d13e5e5d3c1 100644
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IllegalAccessError/IAE_Loader2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 by SAP AG, Walldorf, Germany.
+ * Copyright (c) 2018, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/execstack/Test.java b/test/hotspot/jtreg/runtime/execstack/Test.java
index 67891a523aa..22063a56dd5 100644
--- a/test/hotspot/jtreg/runtime/execstack/Test.java
+++ b/test/hotspot/jtreg/runtime/execstack/Test.java
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 SAP AG. All Rights Reserved.
+ * Copyright (c) 2011, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/execstack/TestMT.java b/test/hotspot/jtreg/runtime/execstack/TestMT.java
index 0be1a461c0a..282b09f9a35 100644
--- a/test/hotspot/jtreg/runtime/execstack/TestMT.java
+++ b/test/hotspot/jtreg/runtime/execstack/TestMT.java
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 SAP AG. All Rights Reserved.
+ * Copyright (c) 2011, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/execstack/libtest-rw.c b/test/hotspot/jtreg/runtime/execstack/libtest-rw.c
index 7ad4b95d25e..52e1e8328a1 100644
--- a/test/hotspot/jtreg/runtime/execstack/libtest-rw.c
+++ b/test/hotspot/jtreg/runtime/execstack/libtest-rw.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 SAP AG. All Rights Reserved.
+ * Copyright (c) 2011, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c b/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c
index bce4f853106..e0d8e424809 100644
--- a/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c
+++ b/test/hotspot/jtreg/runtime/execstack/libtest-rwx.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 SAP AG. All Rights Reserved.
+ * Copyright (c) 2011, 2026 SAP SE. 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
diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java
index a1a5ff68c31..7f1ee4be711 100644
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTimeoutTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -36,7 +36,7 @@
* @library /testlibrary /test/lib
* @build HandshakeTimeoutTest
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
- * @run driver HandshakeTimeoutTest
+ * @run driver/timeout=480 HandshakeTimeoutTest
*/
public class HandshakeTimeoutTest {
diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java
index 50f8385bb6d..27ec125317b 100644
--- a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java
+++ b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java
@@ -25,6 +25,7 @@
* @bug 8328877
* @summary Test warning for GetStringUTFLength and functionality of GetStringUTFLengthAsLong
* @requires vm.bits == 64
+ * @requires os.maxMemory > 15g
* @library /test/lib
* @modules java.management
* @run main/native TestLargeUTF8Length launch
diff --git a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java
index e14cad6cc65..61c38fe782b 100644
--- a/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java
+++ b/test/hotspot/jtreg/runtime/logging/StressAsyncUL.java
@@ -45,12 +45,12 @@ static void analyze_output(boolean stalling_mode, String... args) throws Excepti
}
}
public static void main(String[] args) throws Exception {
- analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", InnerClass.class.getName());
- analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", InnerClass.class.getName());
+ analyze_output(false, "-Xlog:async:drop", "-Xlog:all=debug", InnerClass.class.getName());
+ analyze_output(true, "-Xlog:async:stall", "-Xlog:all=debug", InnerClass.class.getName());
// Stress test with a very small buffer. Note: Any valid buffer size must be able to hold a flush token.
// Therefore the size of the buffer cannot be zero.
- analyze_output(false, "-Xlog:async:drop", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName());
- analyze_output(true, "-Xlog:async:stall", "-Xlog:all=trace", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName());
+ analyze_output(false, "-Xlog:async:drop", "-Xlog:all=debug", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName());
+ analyze_output(true, "-Xlog:async:stall", "-Xlog:all=debug", "-XX:AsyncLogBufferSize=192", InnerClass.class.getName());
}
public static class InnerClass {
diff --git a/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java
index 214751863ea..33cb881e537 100644
--- a/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java
+++ b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java
@@ -39,7 +39,6 @@
*/
import java.lang.invoke.MethodHandles;
-import java.time.Duration;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassTransform;
import java.lang.classfile.MethodTransform;
@@ -61,7 +60,7 @@
public class TestVerify {
- private static final String CLASS_TO_BREAK = "java.time.Duration";
+ private static final String CLASS_TO_BREAK = "java.util.Date";
private static final String INTERNAL_CLASS_TO_BREAK = CLASS_TO_BREAK.replace('.', '/');
private static final boolean DEBUG = false;
@@ -91,7 +90,7 @@ public byte[] transform(Module module, ClassLoader loader, String className, Cla
}
builder.with(element);
});
- var classTransform = ClassTransform.transformingMethods(mm -> mm.methodName().stringValue().equals("getSeconds"), methodTransform);
+ var classTransform = ClassTransform.transformingMethods(mm -> mm.methodName().equalsString("parse"), methodTransform);
byte[] bytes;
try {
@@ -164,7 +163,7 @@ public static void main(String argv[]) throws Exception {
} else {
// Load the class instrumented with CFLH for the VerifyError.
inst.addTransformer(new BadTransformer());
- System.out.println("1 hour is " + Duration.ofHours(1).getSeconds() + " seconds");
+ Class> cls = Class.forName(CLASS_TO_BREAK);
}
throw new RuntimeException("Failed: Did not throw VerifyError");
} catch (VerifyError e) {
diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java
new file mode 100644
index 00000000000..01ea18296e5
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.AfterAll;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.TimeUnit;
+import jdk.test.lib.dcmd.PidJcmdExecutor;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Utils;
+
+/*
+ * @test EarlyDynamicLoad
+ * @summary Test that dynamic attach fails gracefully when the JVM is not in live phase.
+ * @requires vm.jvmti
+ * @library /test/lib
+ * @run junit EarlyDynamicLoad
+ */
+public class EarlyDynamicLoad {
+ private static final String EXPECTED_MESSAGE = "Dynamic agent loading is only permitted in the live phase";
+
+ private static Process child;
+
+ @BeforeAll
+ static void startAndWaitChild() throws Exception {
+ child = ProcessTools.createTestJavaProcessBuilder(
+ "-XX:+StartAttachListener",
+ "-agentpath:" + Utils.TEST_NATIVE_PATH + File.separator + System.mapLibraryName("EarlyDynamicLoad"),
+ "--version").start();
+
+ // Wait until the process enters VMStartCallback
+ try (InputStream is = child.getInputStream()) {
+ is.read();
+ }
+ }
+
+ @AfterAll
+ static void stopChild() throws Exception {
+ try (OutputStream os = child.getOutputStream()) {
+ os.write(0);
+ }
+
+ if (!child.waitFor(5, TimeUnit.SECONDS)) {
+ child.destroyForcibly();
+ throw new AssertionError("Timed out while waiting child process to complete");
+ }
+
+ OutputAnalyzer analyzer = new OutputAnalyzer(child);
+ analyzer.shouldHaveExitValue(0);
+ }
+
+ @Test
+ public void virtualMachine() throws Exception {
+ try {
+ VirtualMachine vm = VirtualMachine.attach(String.valueOf(child.pid()));
+ vm.loadAgent("some.jar");
+ vm.detach();
+ throw new AssertionError("Should have failed with AgentLoadException");
+ } catch(AgentLoadException exception) {
+ if (!exception.getMessage().contains(EXPECTED_MESSAGE)) {
+ throw new AssertionError("Unexpected error message", exception);
+ }
+ }
+ }
+
+ @Test
+ public void jcmd() throws Exception {
+ PidJcmdExecutor executor = new PidJcmdExecutor(String.valueOf(child.pid()));
+ OutputAnalyzer out = executor.execute("JVMTI.agent_load some.jar");
+
+ out.shouldHaveExitValue(0);
+ out.stdoutShouldContain(EXPECTED_MESSAGE);
+ }
+}
diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp
new file mode 100644
index 00000000000..3991926306e
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+
+extern "C" {
+
+static void JNICALL VMStartCallback(jvmtiEnv* jvmti, JNIEnv* env) {
+ putchar('1');
+ fflush(stdout);
+ getchar();
+}
+
+JNIEXPORT int Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
+ jvmtiEnv* jvmti;
+ if (vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_0) != JVMTI_ERROR_NONE) {
+ fprintf(stderr, "JVMTI error occurred during GetEnv\n");
+ return JNI_ERR;
+ }
+
+ jvmtiEventCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.VMStart = VMStartCallback;
+
+ if (jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)) != JVMTI_ERROR_NONE) {
+ fprintf(stderr, "JVMTI error occurred during SetEventCallbacks\n");
+ return JNI_ERR;
+ }
+ if (jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, nullptr) != JVMTI_ERROR_NONE) {
+ fprintf(stderr, "JVMTI error occurred during SetEventNotificationMode\n");
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+}
diff --git a/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java b/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java
index 3e15b24b5d4..22083ee1334 100644
--- a/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java
+++ b/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, 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
@@ -67,7 +67,7 @@ private static void runJCmd(long pid) throws InterruptedException, IOException {
"jcmd exitValue = " + out.getExitValue());
out.shouldHaveExitValue(0);
- out.stderrShouldBeEmptyIgnoreDeprecatedWarnings();
+ out.stderrShouldBeEmptyIgnoreVMWarnings();
}
public static void main(String... args) throws Exception {
diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java
index cc601147714..7e571f7703b 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java
@@ -32,68 +32,27 @@
* @run main/othervm -javaagent:redefineagent.jar ClassVersionAfterRedefine
*/
-import java.io.InputStream;
import java.lang.reflect.Method;
import static jdk.test.lib.Asserts.assertTrue;
public class ClassVersionAfterRedefine extends ClassLoader {
- private static String myName = ClassVersionAfterRedefine.class.getName();
-
- private static byte[] getBytecodes(String name) throws Exception {
- InputStream is = ClassVersionAfterRedefine.class.getResourceAsStream(name + ".class");
- byte[] buf = is.readAllBytes();
- System.out.println("sizeof(" + name + ".class) == " + buf.length);
- return buf;
- }
-
- private static int getStringIndex(String needle, byte[] buf) {
- return getStringIndex(needle, buf, 0);
- }
-
- private static int getStringIndex(String needle, byte[] buf, int offset) {
- outer:
- for (int i = offset; i < buf.length - offset - needle.length(); i++) {
- for (int j = 0; j < needle.length(); j++) {
- if (buf[i + j] != (byte)needle.charAt(j)) continue outer;
- }
- return i;
- }
- return 0;
- }
-
- private static void replaceString(byte[] buf, String name, int index) {
- for (int i = index; i < index + name.length(); i++) {
- buf[i] = (byte)name.charAt(i - index);
- }
- }
-
- private static void replaceAllStrings(byte[] buf, String oldString, String newString) throws Exception {
- assertTrue(oldString.length() == newString.length(), "must have same length");
- int index = -1;
- while ((index = getStringIndex(oldString, buf, index + 1)) != 0) {
- replaceString(buf, newString, index);
- }
- }
-
public static void main(String[] s) throws Exception {
- byte[] buf = getBytecodes("TestClassOld");
- // Poor man's renaming of class "TestClassOld" to "TestClassXXX"
- replaceAllStrings(buf, "TestClassOld", "TestClassXXX");
ClassVersionAfterRedefine cvar = new ClassVersionAfterRedefine();
+
+ byte[] buf = RedefineClassHelper.replaceClassName(cvar, "TestClassOld", "TestClassXXX");
Class> old = cvar.defineClass(null, buf, 0, buf.length);
Method foo = old.getMethod("foo");
Object result = foo.invoke(null);
assertTrue("java-lang-String".equals(result));
System.out.println(old.getSimpleName() + ".foo() = " + result);
- buf = getBytecodes("TestClassNew");
// Rename class "TestClassNew" to "TestClassXXX" so we can use it for
// redefining the original version of "TestClassXXX" (i.e. "TestClassOld").
- replaceAllStrings(buf, "TestClassNew", "TestClassXXX");
- // Now redine the original version of "TestClassXXX" (i.e. "TestClassOld").
+ buf = RedefineClassHelper.replaceClassName(cvar, "TestClassNew", "TestClassXXX");
+ // Now redefine the original version of "TestClassXXX" (i.e. "TestClassOld").
RedefineClassHelper.redefineClass(old, buf);
result = foo.invoke(null);
assertTrue("java.lang.String".equals(result));
diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java
index 7e06cb3af95..0a930485b6d 100644
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java
@@ -75,7 +75,7 @@ private static void runJstackInLoop(LingeredApp app) throws Exception {
System.err.println(out.getStderr());
}
- out.stderrShouldBeEmptyIgnoreDeprecatedWarnings();
+ out.stderrShouldBeEmptyIgnoreVMWarnings();
out.stdoutShouldNotContain("Error occurred during stack walking:");
out.stdoutShouldContain(LingeredAppWithRecComputation.THREAD_NAME);
List stdoutList = Arrays.asList(out.getStdout().split("\\R"));
diff --git a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java
index 798de679d7c..75942f7113a 100644
--- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java
+++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -70,7 +70,7 @@ public static void main(String[] args) throws Exception {
out.shouldNotContain(" prio=0 ");
out.shouldNotContain(" java.lang.Thread.State: UNKNOWN");
- out.stderrShouldBeEmptyIgnoreDeprecatedWarnings();
+ out.stderrShouldBeEmptyIgnoreVMWarnings();
System.out.println("Test Completed");
} catch (Exception ex) {
diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java
new file mode 100644
index 00000000000..ca98506e133
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java
@@ -0,0 +1,87 @@
+
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, NTT DATA
+ * 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.invoke.MethodHandle;
+import java.lang.foreign.Arena;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.Linker;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.SymbolLookup;
+import java.lang.foreign.ValueLayout;
+import java.util.concurrent.CountDownLatch;
+
+import jdk.test.lib.apps.LingeredApp;
+
+public class LingeredAppWithVirtualThread extends LingeredApp implements Runnable {
+
+ private static final String THREAD_NAME = "target thread";
+
+ private static final MethodHandle hndSleep;
+
+ private static final int sleepArg;
+
+ private static final CountDownLatch signal = new CountDownLatch(1);
+
+ static {
+ MemorySegment func;
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ func = SymbolLookup.libraryLookup("Kernel32", Arena.global())
+ .findOrThrow("Sleep");
+ sleepArg = 3600_000; // 1h in milliseconds
+ } else {
+ func = Linker.nativeLinker()
+ .defaultLookup()
+ .findOrThrow("sleep");
+ sleepArg = 3600; // 1h in seconds
+ }
+
+ var desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT);
+ hndSleep = Linker.nativeLinker().downcallHandle(func, desc);
+ }
+
+ @Override
+ public void run() {
+ Thread.yield();
+ signal.countDown();
+ try {
+ hndSleep.invoke(sleepArg);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ Thread.ofVirtual()
+ .name(THREAD_NAME)
+ .start(new LingeredAppWithVirtualThread());
+
+ signal.await();
+ LingeredApp.main(args);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java
index 8d5c95721d5..ac536523815 100644
--- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -68,7 +68,7 @@ public static void main (String... args) throws Exception {
out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$");
out.shouldMatch("^\\s+- waiting on (<0x[0-9a-f]+> \\(a java\\.lang\\.Object\\)|)$");
- out.stderrShouldBeEmptyIgnoreDeprecatedWarnings();
+ out.stderrShouldBeEmptyIgnoreVMWarnings();
System.out.println("Test Completed");
} finally {
diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java
new file mode 100644
index 00000000000..39b6e1ed609
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, NTT DATA
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.SA.SATestUtils;
+import jdk.test.lib.Utils;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/**
+ * @test
+ * @bug 8369505
+ * @requires vm.hasSA
+ * @library /test/lib
+ * @run driver TestJhsdbJstackWithVirtualThread
+ */
+public class TestJhsdbJstackWithVirtualThread {
+
+ private static void runJstack(LingeredApp app) throws Exception {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+ launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-showversion"));
+ launcher.addToolArg("jstack");
+ launcher.addToolArg("--pid");
+ launcher.addToolArg(Long.toString(app.getPid()));
+
+ ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher);
+ Process jhsdb = pb.start();
+ OutputAnalyzer out = new OutputAnalyzer(jhsdb);
+
+ jhsdb.waitFor();
+
+ System.out.println(out.getStdout());
+ System.err.println(out.getStderr());
+
+ out.stderrShouldBeEmptyIgnoreVMWarnings();
+ out.shouldNotContain("must have non-zero frame size");
+ }
+
+ public static void main(String... args) throws Exception {
+ SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
+ LingeredApp app = null;
+
+ try {
+ app = new LingeredAppWithVirtualThread();
+ LingeredApp.startApp(app);
+ System.out.println("Started LingeredApp with pid " + app.getPid());
+ runJstack(app);
+ System.out.println("Test Completed");
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ LingeredApp.stopApp(app);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java
index 8ad0c17ba98..f949f99c035 100644
--- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java
+++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java
@@ -391,13 +391,13 @@ static void testEmptyGenerators() {
Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(1, 0));
Asserts.assertNotNull(G.uniformDoubles(0, 1));
- Asserts.assertNotNull(G.uniformDoubles(0, 0));
+ Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 0));
Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 1).restricted(1.1d, 2.4d));
Asserts.assertNotNull(G.uniformDoubles(0, 1).restricted(0.9d, 2.4d));
Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(1, 0));
Asserts.assertNotNull(G.uniformFloats(0, 1));
- Asserts.assertNotNull(G.uniformFloats(0, 0));
+ Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 0));
Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 1).restricted(1.1f, 2.4f));
Asserts.assertNotNull(G.uniformFloats(0, 1).restricted(0.9f, 2.4f));
@@ -592,8 +592,13 @@ static void testFuzzy() {
var floatBoundGen = G.uniformFloats();
for (int j = 0; j < 500; j++) {
- float a = floatBoundGen.next(), b = floatBoundGen.next();
- float lo = Math.min(a, b), hi = Math.max(a, b);
+ float lo = 1, hi = 0;
+ // Failure of a single round is very rare, repeated failure even rarer.
+ while (lo >= hi) {
+ float a = floatBoundGen.next(), b = floatBoundGen.next();
+ lo = Math.min(a, b);
+ hi = Math.max(a, b);
+ }
var gb = G.uniformFloats(lo, hi);
for (int i = 0; i < 10_000; i++) {
float x = gb.next();
@@ -604,8 +609,13 @@ static void testFuzzy() {
var doubleBoundGen = G.uniformDoubles();
for (int j = 0; j < 500; j++) {
- double a = doubleBoundGen.next(), b = doubleBoundGen.next();
- double lo = Math.min(a, b), hi = Math.max(a, b);
+ double lo = 1, hi = 0;
+ // Failure of a single round is very rare, repeated failure even rarer.
+ while (lo >= hi) {
+ double a = doubleBoundGen.next(), b = doubleBoundGen.next();
+ lo = Math.min(a, b);
+ hi = Math.max(a, b);
+ }
var gb = G.uniformDoubles(lo, hi);
for (int i = 0; i < 10_000; i++) {
double x = gb.next();
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java
index a2d98d00502..fe21dce73b5 100644
--- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java
@@ -60,6 +60,7 @@ public class TestPhaseIRMatching {
public static void main(String[] args) {
run(Basics.class);
run(NoCompilationOutput.class);
+ run(LoadStore.class);
}
private static void run(Class> testClass) {
@@ -549,3 +550,239 @@ public static List sort(Set failures) {
.thenComparing(Failure::constraintId)).collect(Collectors.toList());
}
}
+
+// Test load and store regexes
+class LoadStore {
+ int i;
+ float f;
+ interface I1 {}
+ static class Base implements I1 {
+ int i;
+ }
+ interface I2 {}
+ static class Derived extends Base implements I2 {
+ long l;
+ }
+ Base base = new Base();
+ Derived derived = new Derived();
+
+ static class SingleNest {
+ static class DoubleNest {
+ int i;
+ }
+ }
+
+ SingleNest.DoubleNest doubleNest = new SingleNest.DoubleNest();
+
+
+ @Test
+ @IR(failOn = {IRNode.LOAD_OF_CLASS, ".*", IRNode.STORE_OF_CLASS, ".*"})
+ public void triviallyFailBoth() {
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.LOAD_OF_CLASS, "LoadS[a-z]+", "1",
+ IRNode.LOAD_OF_CLASS, "Load.tore", "1",
+ IRNode.LOAD_OF_CLASS, "LoadStore", "1",
+ IRNode.LOAD_OF_CLASS, "/LoadStore", "1",
+ IRNode.LOAD_OF_CLASS, "tests/LoadStore", "1",
+ IRNode.LOAD_OF_CLASS, "/tests/LoadStore", "1",
+ IRNode.LOAD_OF_CLASS, "ir_framework/tests/LoadStore", "1",
+ IRNode.LOAD_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1", // To assert it's the whole qualification
+ IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.LOAD_OF_CLASS, "oadStore",
+ IRNode.LOAD_OF_CLASS, "LoadStor",
+ IRNode.LOAD_OF_CLASS, "/ir_framework/tests/LoadStore",
+ IRNode.LOAD_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore+12 *
+ public float simpleLoad() {
+ return f;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.STORE_OF_CLASS, "LoadS[a-z]+", "1",
+ IRNode.STORE_OF_CLASS, "Load.tore", "1",
+ IRNode.STORE_OF_CLASS, "LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "/LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "tests/LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "/tests/LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "ir_framework/tests/LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore", "1",
+ IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.STORE_OF_CLASS, "oadStore",
+ IRNode.STORE_OF_CLASS, "LoadStor",
+ IRNode.STORE_OF_CLASS, "/ir_framework/tests/LoadStore",
+ IRNode.STORE_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore+12 *
+ public void simpleStore() {
+ i = 1;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.LOAD_I_OF_CLASS, "Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "Load.tore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1",
+ IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.LOAD_I_OF_CLASS, "/Base",
+ IRNode.LOAD_I_OF_CLASS, "oadStore\\$Base",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore\\$Bas",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore",
+ IRNode.LOAD_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base",
+ IRNode.LOAD_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 *
+ public int loadWithInterface() {
+ return base.i;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.STORE_I_OF_CLASS, "Base", "1",
+ IRNode.STORE_I_OF_CLASS, "\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "LoadS[a-z]+\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "Load.tore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "/LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Base", "1",
+ IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.STORE_I_OF_CLASS, "/Base",
+ IRNode.STORE_I_OF_CLASS, "oadStore\\$Base",
+ IRNode.STORE_I_OF_CLASS, "LoadStore\\$Bas",
+ IRNode.STORE_I_OF_CLASS, "LoadStore",
+ IRNode.STORE_I_OF_CLASS, "/ir_framework/tests/LoadStore\\$Base",
+ IRNode.STORE_I_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore$Base (ir_framework/tests/LoadStore$I1)+12 *
+ public void storeWithInterface() {
+ base.i = 1;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.LOAD_L_OF_CLASS, "Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "Load.tore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "/LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "tests/LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1",
+ IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.LOAD_L_OF_CLASS, "/Derived",
+ IRNode.LOAD_L_OF_CLASS, "oadStore\\$Derived",
+ IRNode.LOAD_L_OF_CLASS, "LoadStore\\$Derive",
+ IRNode.LOAD_L_OF_CLASS, "LoadStore",
+ IRNode.LOAD_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived",
+ IRNode.LOAD_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 *
+ public long loadWithInterfaces() {
+ return derived.l;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.STORE_L_OF_CLASS, "Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "LoadS[a-z]+\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "Load.tore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "/LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "tests/LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "/tests/LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "ir_framework/tests/LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "(?<=[@: ])ir_framework/tests/LoadStore\\$Derived", "1",
+ IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$/]*tests[\\w\\$/]*", "1",
+ },
+ failOn = {
+ IRNode.STORE_L_OF_CLASS, "/Derived",
+ IRNode.STORE_L_OF_CLASS, "oadStore\\$Derived",
+ IRNode.STORE_L_OF_CLASS, "LoadStore\\$Derive",
+ IRNode.STORE_L_OF_CLASS, "LoadStore",
+ IRNode.STORE_L_OF_CLASS, "/ir_framework/tests/LoadStore\\$Derived",
+ IRNode.STORE_L_OF_CLASS, "(?<=[@: ])[\\w\\$]*tests[\\w\\$]*",
+ }
+ )
+ // @ir_framework/tests/LoadStore$Derived (ir_framework/tests/LoadStore$I1,ir_framework/tests/LoadStore$I2)+24 *
+ public void storeWithInterfaces() {
+ derived.l = 1;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.LOAD_I_OF_CLASS, "DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.LOAD_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ },
+ failOn = {
+ IRNode.LOAD_I_OF_CLASS, "SingleNest",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore",
+ IRNode.LOAD_I_OF_CLASS, "LoadStore\\$SingleNest",
+ }
+ )
+ // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 *
+ public int loadDoubleNested() {
+ return doubleNest.i;
+ }
+
+ @Test
+ @IR(counts = {
+ IRNode.STORE_I_OF_CLASS, "DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "\\$SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "/tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ IRNode.STORE_I_OF_CLASS, "ir_framework/tests/LoadStore\\$SingleNest\\$DoubleNest", "1",
+ },
+ failOn = {
+ IRNode.STORE_I_OF_CLASS, "SingleNest",
+ IRNode.STORE_I_OF_CLASS, "LoadStore",
+ IRNode.STORE_I_OF_CLASS, "LoadStore\\$SingleNest",
+ }
+ )
+ // @ir_framework/tests/LoadStore$SingleNest$DoubleNest+12 *
+ public void storeDoubleNested() {
+ doubleNest.i = 1;
+ }
+}
\ No newline at end of file
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java
index a729aa4d28f..09d54318b60 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -37,7 +37,7 @@
* Test scenario:
* - during initialization (from function Agent_OnAttach) agent starts auxiliary thread waiting on
* raw monitor and enables GarbageCollectionStart and GarbageCollectionFinish events
- * - target application provokes garbage collection (calls System.gc())
+ * - target application provokes garbage collection (calls WhiteBox.getWhiteBox().fullGC())
* - agent receives event GarbageCollectionStart
* - agent receives event GarbageCollectionFinish event and notifies waiting auxiliary thread
* - notified auxiliary thread notifies target application that agent finished its work
@@ -48,11 +48,13 @@
* /test/lib
* @build nsk.share.aod.AODTestRunner
* nsk.jvmti.AttachOnDemand.attach020.attach020Target
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm/native
* nsk.share.aod.AODTestRunner
* -jdk ${test.jdk}
* -target nsk.jvmti.AttachOnDemand.attach020.attach020Target
- * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
+ * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI"
* -na attach020Agent00
*/
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java
index a20cf935bae..3a52a539b82 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/attach020Target.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,14 +22,14 @@
*/
package nsk.jvmti.AttachOnDemand.attach020;
-import nsk.share.ClassUnloader;
import nsk.share.aod.TargetApplicationWaitingAgents;
+import jdk.test.whitebox.WhiteBox;
public class attach020Target extends TargetApplicationWaitingAgents {
protected void targetApplicationActions() {
log.display("Provoking garbage collection");
- ClassUnloader.eatMemory();
+ WhiteBox.getWhiteBox().fullGC();
}
public static void main(String[] args) {
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java
index 5cf7b39729b..3d8dc2f4e85 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -44,11 +44,13 @@
* /test/lib
* @build nsk.share.aod.AODTestRunner
* nsk.jvmti.AttachOnDemand.attach021.attach021Target
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm/native
* nsk.share.aod.AODTestRunner
* -jdk ${test.jdk}
* -target nsk.jvmti.AttachOnDemand.attach021.attach021Target
- * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
+ * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI"
* -na attach021Agent00
*/
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java
index d287616af69..adb2c194189 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Target.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,8 +22,8 @@
*/
package nsk.jvmti.AttachOnDemand.attach021;
-import nsk.share.ClassUnloader;
import nsk.share.aod.TargetApplicationWaitingAgents;
+import jdk.test.whitebox.WhiteBox;
public class attach021Target extends TargetApplicationWaitingAgents {
@@ -51,7 +51,7 @@ protected void targetApplicationActions() throws Throwable {
try {
if (createTaggedObject()) {
log.display("Provoking GC");
- ClassUnloader.eatMemory();
+ WhiteBox.getWhiteBox().fullGC();
}
} finally {
shutdownAgent();
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java
index 49b47585749..5875f7a0f50 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -47,11 +47,13 @@
* /test/lib
* @build nsk.share.aod.AODTestRunner
* nsk.jvmti.AttachOnDemand.attach022.attach022Target
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm/native
* nsk.share.aod.AODTestRunner
* -jdk ${test.jdk}
* -target nsk.jvmti.AttachOnDemand.attach022.attach022Target
- * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
+ * -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts} -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI"
* -na attach022Agent00
*/
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java
index eb80c0c2a4c..3324855e622 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Target.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,8 +22,8 @@
*/
package nsk.jvmti.AttachOnDemand.attach022;
-import nsk.share.ClassUnloader;
import nsk.share.aod.TargetApplicationWaitingAgents;
+import jdk.test.whitebox.WhiteBox;
class ClassForAllocationEventsTest {
@@ -47,7 +47,7 @@ protected void targetApplicationActions() throws Throwable {
}
log.display("Provoking GC");
- ClassUnloader.eatMemory();
+ WhiteBox.getWhiteBox().fullGC();
} finally {
if (!shutdownAgent(TEST_ALLOCATION_NUMBER)) {
setStatusFailed("Error happened during agent work, see error messages for details");
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java
index 433ee607d7c..3e25000a2fb 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GarbageCollectionFinish/gcfinish001.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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 @@
import java.math.*;
import nsk.share.*;
+import jdk.test.whitebox.WhiteBox;
/**
* This test exercises the JVMTI event GarbageCollectionFinish.
@@ -63,7 +64,7 @@ public static int run(String argv[], PrintStream out) {
private int runThis(String argv[], PrintStream out) {
try {
for (int i=0; iGarbageCollectionStart.
@@ -63,13 +64,7 @@ public static int run(String argv[], PrintStream out) {
}
private int runThis(String argv[], PrintStream out) {
- try {
- for (int i=0; iGarbageCollectionStart.
@@ -61,13 +62,7 @@ public static int run(String argv[], PrintStream out) {
}
private int runThis(String argv[], PrintStream out) {
- try {
- for (int i=0; iRawMonitorExit(syncLock);
-
- if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
- nsk_jvmti_setFailStatus();
-
}
/* ============================================================================= */
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
index 5ea01fb3af4..e3b6693657c 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -28,7 +28,7 @@
package nsk.share;
-import java.lang.ref.Cleaner;
+import java.lang.ref.PhantomReference;
import java.util.*;
import nsk.share.gc.gp.*;
import nsk.share.test.ExecutionController;
@@ -77,19 +77,9 @@ public class ClassUnloader {
public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader";
/**
- * Whole amount of time in milliseconds to wait for class loader to be reclaimed.
+ * Phantom reference to the class loader.
*/
- private static final int WAIT_TIMEOUT = 15000;
-
- /**
- * Sleep time in milliseconds for the loop waiting for the class loader to be reclaimed.
- */
- private static final int WAIT_DELTA = 1000;
-
- /**
- * Has class loader been reclaimed or not.
- */
- volatile boolean is_reclaimed = false;
+ private PhantomReference customClassLoaderPhantomRef = null;
/**
* Current class loader used for loading classes.
@@ -101,6 +91,14 @@ public class ClassUnloader {
*/
private Vector> classObjects = new Vector>();
+ /**
+ * Has class loader been reclaimed or not.
+ */
+ private boolean isClassLoaderReclaimed() {
+ return customClassLoaderPhantomRef != null
+ && customClassLoaderPhantomRef.refersTo(null);
+ }
+
/**
* Class object of the first class been loaded with current class loader.
* To get the rest loaded classes use getLoadedClass(int).
@@ -138,8 +136,7 @@ public CustomClassLoader createClassLoader() {
customClassLoader = new CustomClassLoader();
classObjects.removeAllElements();
- // Register a Cleaner to inform us when the class loader has been reclaimed.
- Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } );
+ customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null);
return customClassLoader;
}
@@ -154,8 +151,7 @@ public void setClassLoader(CustomClassLoader customClassLoader) {
this.customClassLoader = customClassLoader;
classObjects.removeAllElements();
- // Register a Cleaner to inform us when the class loader has been reclaimed.
- Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } );
+ customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null);
}
/**
@@ -244,32 +240,15 @@ public void loadClass(String className, String classDir) throws ClassNotFoundExc
*/
public boolean unloadClass(ExecutionController stresser) {
- is_reclaimed = false;
-
// free references to class and class loader to be able for collecting by GC
- long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT;
classObjects.removeAllElements();
customClassLoader = null;
// force class unloading by eating memory pool
eatMemory(stresser);
- // give GC chance to run and wait for receiving reclaim notification
- long timeToFinish = System.currentTimeMillis() + waitTimeout;
- while (!is_reclaimed && System.currentTimeMillis() < timeToFinish) {
- if (!stresser.continueExecution()) {
- return false;
- }
- try {
- // suspend thread for a while
- Thread.sleep(WAIT_DELTA);
- } catch (InterruptedException e) {
- throw new Failure("Unexpected InterruptedException while class unloading: " + e);
- }
- }
-
// force GC to unload marked class loader and its classes
- if (is_reclaimed) {
+ if (isClassLoaderReclaimed()) {
Runtime.getRuntime().gc();
return true;
}
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
index 6b33783306f..15bbc9eb964 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
@@ -48,6 +48,9 @@ protected static class GCTestRunner extends TestRunner {
public GCTestRunner(Test test, String[] args) {
super(test, args);
+ // GC tests often run at the brink of OOME, make sure
+ // LocalRandom is loaded, initialized, and has enough memory.
+ LocalRandom.init();
}
private GCParams getGCParams(String[] args) {
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java
index 0668297d211..86d5d7ecd24 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -149,19 +149,11 @@ public void loadTestClass(String className) {
}
}
- public static final int MAX_UNLOAD_ATTEMPS = 5;
-
public void unloadTestClass(String className, boolean expectedUnloadingResult) {
ClassUnloader classUnloader = loadedClasses.get(className);
- int unloadAttemps = 0;
-
if (classUnloader != null) {
- boolean wasUnloaded = false;
-
- while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) {
- wasUnloaded = classUnloader.unloadClass();
- }
+ boolean wasUnloaded = classUnloader.unloadClass();
if (wasUnloaded)
loadedClasses.remove(className);
diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java
index c8264e8f963..abb771e30e7 100644
--- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java
+++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -33,6 +33,7 @@
* another method handle and so on.
* The test verifies that arguments are correctly passed between native methods and MHs.
*
+ * @requires vm.compMode != "Xcomp"
* @library /vmTestbase
* /test/lib
*
@@ -62,26 +63,32 @@ public class Test extends MultiThreadedTest {
private static final String RETURN_VALUE = "test";
+ private static final MethodType MT_calledFromNative = MethodType.methodType(
+ Object.class,
+ Object.class, Object.class, int.class, long.class, double.class, float.class);
+
+ private static MethodHandle mh;
+
static {
System.loadLibrary("nativeAndMH");
+ try {
+ mh = MethodHandles.lookup().findStatic(
+ Test.class,
+ "calledFromNative",
+ MT_calledFromNative);
+ } catch (Exception ex) {
+ throw new RuntimeException("TEST FAILED - Unable to lookup \"calledFromNative\"");
+ }
}
private static native Object native01(Object a1, String a2, Object a3, Object a4, Object a5, Object a6, MethodHandle mh);
- private static final MethodType MT_calledFromNative = MethodType.methodType(
- Object.class,
- Object.class, Object.class, int.class, long.class, double.class, float.class);
-
private static Object calledFromNative(Object s1, Object s2, int i, long l, double d, float f) {
return RETURN_VALUE;
}
@Override
protected boolean runThread(int threadNum) throws Throwable {
- MethodHandle mh = MethodHandles.lookup().findStatic(
- Test.class,
- "calledFromNative",
- MT_calledFromNative);
Stresser stresser = createStresser();
stresser.start(1);
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 72af3f18522..6418e1dfb36 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -119,7 +119,6 @@ java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generi
java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all
-java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java 8361521 linux-all
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340374 macosx-all
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all
@@ -553,8 +552,6 @@ java/io/IO/IO.java 8337935 linux-pp
# jdk_management
-com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all
-com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all
java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all
java/lang/management/MemoryMXBean/PendingAllGC.sh 8158837 generic-all
@@ -569,7 +566,6 @@ sun/management/jdp/JdpOffTest.java 8308807 aix-ppc6
# jdk_jmx
-javax/management/MBeanServer/OldMBeanServerTest.java 8030957 aix-all
javax/management/remote/mandatory/connection/BrokenConnectionTest.java 8262312 linux-all
@@ -596,8 +592,6 @@ java/net/MulticastSocket/Test.java 7145658,8308807
# jdk_nio
-java/nio/channels/Channels/SocketChannelStreams.java 8317838 aix-ppc64
-
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64
@@ -614,8 +608,6 @@ java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java 7140992 generi
java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-all
-java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all
-
java/rmi/registry/readTest/CodebaseTest.java 8173324 windows-all
java/rmi/registry/multipleRegistries/MultipleRegistries.java 8268182 macosx-all
diff --git a/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java b/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java
new file mode 100644
index 00000000000..133e68b344f
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/Cipher/AES/TestGCMSplitBound.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2025, Google LLC. 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 8371864
+ * @run main/othervm/timeout=600 TestGCMSplitBound
+ * @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx2.*" |
+ * vm.cpu.features ~= ".*avx512.*"))
+ * @summary Test GaloisCounterMode.implGCMCrypt0 AVX512/AVX2 intrinsics.
+ */
+
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.time.Duration;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TestGCMSplitBound {
+
+ static final SecureRandom SECURE_RANDOM = newDefaultSecureRandom();
+
+ private static SecureRandom newDefaultSecureRandom() {
+ SecureRandom retval = new SecureRandom();
+ retval.nextLong(); // force seeding
+ return retval;
+ }
+
+ private static byte[] randBytes(int size) {
+ byte[] rand = new byte[size];
+ SECURE_RANDOM.nextBytes(rand);
+ return rand;
+ }
+
+ private static final int IV_SIZE_IN_BYTES = 12;
+ private static final int TAG_SIZE_IN_BYTES = 16;
+
+ private Cipher getCipher(final byte[] key, final byte[] aad,
+ final byte[] nonce, int mode)
+ throws Exception {
+ SecretKey keySpec = new SecretKeySpec(key, "AES");
+ AlgorithmParameterSpec params =
+ new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, nonce, 0, nonce.length);
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(mode, keySpec, params);
+ if (aad != null && aad.length != 0) {
+ cipher.updateAAD(aad);
+ }
+ return cipher;
+ }
+
+ private byte[] gcmEncrypt(final byte[] key, final byte[] plaintext,
+ final byte[] aad)
+ throws Exception {
+ byte[] nonce = randBytes(IV_SIZE_IN_BYTES);
+ Cipher cipher = getCipher(key, aad, nonce, Cipher.ENCRYPT_MODE);
+ int outputSize = cipher.getOutputSize(plaintext.length);
+ int len = IV_SIZE_IN_BYTES + outputSize;
+ byte[] output = new byte[len];
+ System.arraycopy(nonce, 0, output, 0, IV_SIZE_IN_BYTES);
+ cipher.doFinal(plaintext, 0, plaintext.length, output,
+ IV_SIZE_IN_BYTES);
+ return output;
+ }
+
+ private byte[] gcmDecrypt(final byte[] key, final byte[] ciphertext,
+ final byte[] aad)
+ throws Exception {
+ byte[] nonce = new byte[IV_SIZE_IN_BYTES];
+ System.arraycopy(ciphertext, 0, nonce, 0, IV_SIZE_IN_BYTES);
+ Cipher cipher = getCipher(key, aad, nonce, Cipher.DECRYPT_MODE);
+ return cipher.doFinal(ciphertext, IV_SIZE_IN_BYTES,
+ ciphertext.length - IV_SIZE_IN_BYTES);
+ }
+
+ // x86-64 parallel intrinsic data size
+ private static final int PARALLEL_LEN = 512;
+ // max data size for x86-64 intrinsic
+ private static final int SPLIT_LEN = 1048576; // 1MB
+
+ private void encryptAndDecrypt(byte[] key, byte[] aad, byte[] message,
+ int messageSize)
+ throws Exception {
+ byte[] ciphertext = gcmEncrypt(key, message, aad);
+ byte[] decrypted = gcmDecrypt(key, ciphertext, aad);
+ if (ciphertext == null) {
+ throw new RuntimeException("ciphertext is null");
+ }
+ if (Arrays.compare(decrypted, 0, messageSize,
+ message, 0, messageSize) != 0) {
+ throw new RuntimeException(
+ "Decrypted message is different from the original message");
+ }
+ }
+
+ private void run() throws Exception {
+ byte[] aad = randBytes(20);
+ byte[] key = randBytes(16);
+ // Force JIT.
+ for (int i = 0; i < 100000; i++) {
+ byte[] message = randBytes(PARALLEL_LEN);
+ encryptAndDecrypt(key, aad, message, PARALLEL_LEN);
+ }
+ for (int messageSize = SPLIT_LEN - 300; messageSize <= SPLIT_LEN + 300;
+ messageSize++) {
+ byte[] message = randBytes(messageSize);
+ try {
+ encryptAndDecrypt(key, aad, message, messageSize);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed for messageSize "
+ + Integer.toHexString(messageSize), e);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ TestGCMSplitBound test = new TestGCMSplitBound();
+ for (int i = 0; i < 3; i++) {
+ test.run();
+ }
+ }
+}
diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java b/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java
index cb90f374d84..7824b030d41 100644
--- a/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java
+++ b/test/jdk/com/sun/java/swing/plaf/gtk/4928019/bug4928019.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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,25 +26,25 @@
* @bug 4928019
* @key headful
* @summary Makes sure all the basic classes can be created with GTK.
- * @author Scott Violet
+ * @requires (os.family != "windows" & os.family != "mac")
+ * @library /test/lib
+ * @build jtreg.SkippedException
+ * @run main bug4928019
*/
import javax.swing.*;
import javax.swing.plaf.basic.*;
+import jtreg.SkippedException;
+
public class bug4928019 {
public static void main(String[] args) throws Throwable {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
- } catch (UnsupportedLookAndFeelException ex) {
- System.err.println("GTKLookAndFeel is not supported on this platform." +
- " Test is considered passed.");
- return;
- } catch (ClassNotFoundException ex) {
- System.err.println("GTKLookAndFeel class is not found." +
- " Test is considered passed.");
- return;
+ } catch (Exception e) {
+ throw new SkippedException("GTKLookAndFeel isn't supported", e);
}
+
new JButton() {
public void updateUI() {
setUI(new BasicButtonUI());
diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java b/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java
index ddf8363e2ee..eb3e1e7ca62 100644
--- a/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java
+++ b/test/jdk/com/sun/java/swing/plaf/gtk/Test6635110.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -21,18 +21,28 @@
* questions.
*/
-/* @test
- @bug 6635110
- @key headful
- @summary GTK icons should not throw NPE when called by non-GTK UI
- @author Peter Zhelezniakov
- @run main Test6635110
+/*
+ * @test
+ * @bug 6635110
+ * @key headful
+ * @summary GTK icons should not throw NPE when called by non-GTK UI
+ * @requires (os.family != "windows" & os.family != "mac")
+ * @library /test/lib
+ * @build jtreg.SkippedException
+ * @run main Test6635110
*/
-import javax.swing.*;
-import java.awt.*;
+import java.awt.Component;
import java.awt.image.BufferedImage;
-import javax.swing.plaf.basic.*;
+
+import javax.swing.JMenu;
+import javax.swing.JToolBar;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicMenuUI;
+import javax.swing.plaf.basic.BasicToolBarUI;
+
+import jtreg.SkippedException;
public class Test6635110 implements Runnable {
@@ -53,7 +63,7 @@ public class Test6635110 implements Runnable {
paint(tb);
}
- void paint(Component c) {
+ private void paint(Component c) {
c.setSize(WIDTH, HEIGHT);
c.paint(IMAGE.getGraphics());
}
@@ -62,9 +72,9 @@ public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (Exception e) {
- System.out.println("GTKLookAndFeel cannot be set, skipping this test");
- return;
+ throw new SkippedException("GTKLookAndFeel isn't supported", e);
}
+
SwingUtilities.invokeAndWait(new Test6635110());
}
}
diff --git a/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java b/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java
index 962a2d1a0af..ea072419a59 100644
--- a/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java
+++ b/test/jdk/com/sun/java/swing/plaf/gtk/Test6963870.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -21,23 +21,28 @@
* questions.
*/
-/* @test
- @bug 6963870
- @key headful
- @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets()
- doesn't return null
- @author Peter Zhelezniakov
- @run main Test6963870
-*/
+/*
+ * @test
+ * @bug 6963870
+ * @key headful
+ * @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets()
+ * doesn't return null
+ * @requires (os.family != "windows" & os.family != "mac")
+ * @library /test/lib
+ * @build jtreg.SkippedException
+ * @run main Test6963870
+ */
import java.awt.Insets;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
+import jtreg.SkippedException;
+
public class Test6963870 implements Runnable {
- final static String[] UI_NAMES = {
+ static final String[] UI_NAMES = {
"List.focusCellHighlightBorder",
"List.focusSelectedCellHighlightBorder",
"List.noFocusBorder",
@@ -45,6 +50,7 @@ public class Test6963870 implements Runnable {
"Table.focusSelectedCellHighlightBorder",
};
+ @Override
public void run() {
for (String uiName: UI_NAMES) {
test(uiName);
@@ -63,11 +69,9 @@ public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (Exception e) {
- System.out.println("GTKLookAndFeel cannot be set, skipping this test");
- return;
+ throw new SkippedException("GTKLookAndFeel isn't supported", e);
}
SwingUtilities.invokeAndWait(new Test6963870());
}
}
-
diff --git a/test/jdk/com/sun/jdi/TwoThreadsTest.java b/test/jdk/com/sun/jdi/TwoThreadsTest.java
index e38783f3ea6..e5732ffd8d1 100644
--- a/test/jdk/com/sun/jdi/TwoThreadsTest.java
+++ b/test/jdk/com/sun/jdi/TwoThreadsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -55,6 +55,13 @@ public static void main(String[] args) {
t1.start();
t2.start();
+ // The threads might be virtual and daemon, so wait until completion.
+ try {
+ t1.join();
+ t2.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
diff --git a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java
index 123c5120daf..d7d0f9a8392 100644
--- a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java
+++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java
@@ -35,6 +35,8 @@
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
+
+import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
@@ -82,14 +84,10 @@ public void test() throws Exception {
env.put(Context.PROVIDER_URL, "ldap://example.com:1234");
try {
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
- futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
+ // launch a few concurrent connection attempts
+ for (int i = 0; i < 8; i++) {
+ futures.add(executorService.submit(() -> { attemptConnect(env); return null; }));
+ }
} finally {
executorService.shutdown();
}
@@ -109,39 +107,56 @@ public void test() throws Exception {
private static void attemptConnect(Hashtable env) throws Exception {
try {
- LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000,
- 2 * CONNECT_MILLIS + TOLERANCE,
- () -> new InitialDirContext(env));
- } catch (RuntimeException e) {
- final String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
- // assertCompletion may wrap a CommunicationException in an RTE
- if (msg != null &&
- (msg.contains("Network is unreachable")
- || msg.contains("No route to host")
- || msg.contains("Connection timed out"))) {
- // got the expected exception
- System.out.println("Received expected RuntimeException message: " + msg);
- } else {
- // propagate the unexpected exception
- throw e;
+ final InitialDirContext unexpectedCtx =
+ LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000,
+ 2 * CONNECT_MILLIS + TOLERANCE,
+ () -> new InitialDirContext(env));
+ throw new RuntimeException("InitialDirContext construction was expected to fail," +
+ " but returned " + unexpectedCtx);
+ } catch (Throwable t) {
+ final NamingException namingEx = findNamingException(t);
+ if (namingEx != null) {
+ // found the NamingException, verify it's the right reason
+ if (namingEx.getCause() instanceof SocketTimeoutException ste) {
+ // got the expected exception
+ System.out.println("Received expected SocketTimeoutException: " + ste);
+ return;
+ }
+ // rely on the exception message to verify the expected exception
+ final String msg = namingEx.getCause() == null
+ ? namingEx.getMessage()
+ : namingEx.getCause().getMessage();
+ if (msg != null &&
+ (msg.contains("Network is unreachable")
+ || msg.contains("No route to host")
+ || msg.contains("Timed out waiting for lock")
+ || msg.contains("Connect timed out")
+ || msg.contains("Timeout exceeded while waiting for a connection"))) {
+ // got the expected exception
+ System.out.println("Received expected NamingException with message: " + msg);
+ return;
+ }
}
- } catch (NamingException ex) {
- final String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage();
- if (msg != null &&
- (msg.contains("Network is unreachable")
- || msg.contains("Timed out waiting for lock")
- || msg.contains("Connect timed out")
- || msg.contains("Timeout exceeded while waiting for a connection"))) {
- // got the expected exception
- System.out.println("Received expected NamingException message: " + msg);
+ // unexpected exception, propagate it
+ if (t instanceof Exception e) {
+ throw e;
} else {
- // propagate the unexpected exception
- throw ex;
+ throw new Exception(t);
}
- } catch (Throwable t) {
- throw new RuntimeException(t);
}
}
+ // Find and return the NamingException from the given Throwable. Returns null if none found.
+ private static NamingException findNamingException(final Throwable t) {
+ Throwable cause = t;
+ while (cause != null) {
+ if (cause instanceof NamingException ne) {
+ return ne;
+ }
+ cause = cause.getCause();
+ }
+ return null;
+ }
+
}
diff --git a/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java b/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java
index 81561160725..e8f365b715b 100644
--- a/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java
+++ b/test/jdk/com/sun/net/httpserver/ServerStopTerminationTest.java
@@ -124,13 +124,16 @@ public void shouldAwaitActiveExchange() throws InterruptedException {
// Complete the exchange one second into the future
final Duration exchangeDuration = Duration.ofSeconds(1);
+ // taking start time before entering completeExchange to account for possible
+ // delays in reaching server.stop().
+ final long startTime = System.nanoTime();
completeExchange(exchangeDuration);
log("Complete Exchange triggered");
// Time the shutdown sequence
- final Duration delayDuration = Duration.ofSeconds(Utils.adjustTimeout(5));
+ final Duration delayDuration = Duration.ofSeconds(Utils.adjustTimeout(20));
log("Shutdown triggered with the delay of " + delayDuration.getSeconds());
- final long elapsed = timeShutdown(delayDuration);
+ final long elapsed = timeShutdown(delayDuration, startTime);
log("Shutdown complete");
// The shutdown should take at least as long as the exchange duration
@@ -151,31 +154,20 @@ public void shouldAwaitActiveExchange() throws InterruptedException {
* @throws InterruptedException if an unexpected interruption occurs
*/
@Test
- public void shouldCompeteAfterDelay() throws InterruptedException {
+ public void shouldCompleteAfterDelay() throws InterruptedException {
// Initiate an exchange
startExchange();
// Wait for the server to receive the exchange
start.await();
log("Exchange started");
- // Complete the exchange 10 second into the future.
- // Runs in parallel, so won't block the server stop
- final Duration exchangeDuration = Duration.ofSeconds(Utils.adjustTimeout(10));
- completeExchange(exchangeDuration);
- log("Complete Exchange triggered");
-
-
// Time the shutdown sequence
final Duration delayDuration = Duration.ofSeconds(1);
log("Shutdown triggered with the delay of " + delayDuration.getSeconds());
final long elapsed = timeShutdown(delayDuration);
log("Shutdown complete");
-
-
- // The shutdown should not await the exchange to complete
- if (elapsed >= exchangeDuration.toNanos()) {
- fail("HttpServer.stop terminated too late");
- }
+ complete.countDown();
+ log("Exchange completed");
// The shutdown delay should have expired
if (elapsed < delayDuration.toNanos()) {
@@ -277,7 +269,14 @@ public void shouldAllowRepeatedStop() {
*/
private long timeShutdown(Duration delayDuration) {
final long startTime = System.nanoTime();
+ return timeShutdown(delayDuration, startTime);
+ }
+ /**
+ * This allows passing a custom start time
+ */
+ private long timeShutdown(Duration delayDuration,
+ long startTime) {
server.stop((int) delayDuration.toSeconds());
return System.nanoTime() - startTime;
}
diff --git a/test/jdk/com/sun/net/httpserver/Test9.java b/test/jdk/com/sun/net/httpserver/Test9.java
index 6f7b1d4f5bc..6051de96596 100644
--- a/test/jdk/com/sun/net/httpserver/Test9.java
+++ b/test/jdk/com/sun/net/httpserver/Test9.java
@@ -59,7 +59,7 @@ public class Test9 extends Test {
HttpServer.class.getPackageName() + '-' + Test9.class.getSimpleName() + '-';
static SSLContext ctx;
- static boolean error = false;
+ static volatile boolean error = false;
public static void main (String[] args) throws Exception {
HttpServer s1 = null;
@@ -67,6 +67,8 @@ public static void main (String[] args) throws Exception {
ExecutorService executor=null;
Path smallFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23);
Path largeFilePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 2730088);
+ smallFilePath.toFile().deleteOnExit();
+ largeFilePath.toFile().deleteOnExit();
try {
System.out.print ("Test9: ");
InetAddress loopback = InetAddress.getLoopbackAddress();
@@ -122,20 +124,16 @@ public static void main (String[] args) throws Exception {
s2.stop(0);
if (executor != null)
executor.shutdown ();
- Files.delete(smallFilePath);
- Files.delete(largeFilePath);
}
}
- static int foo = 1;
-
static ClientThread test (boolean fixedLen, String protocol, int port, Path filePath) throws Exception {
ClientThread t = new ClientThread (fixedLen, protocol, port, filePath);
t.start();
return t;
}
- static Object fileLock = new Object();
+ static final Object fileLock = new Object();
static class ClientThread extends Thread {
@@ -203,9 +201,8 @@ public boolean verify (String s, SSLSession s1) {
error = true;
}
assertFileContentsEqual(filePath, temp.toPath());
- temp.delete();
} catch (Exception e) {
- e.printStackTrace();
+ System.err.println("Error occurred: " + e);
error = true;
}
}
diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java
index d6ec3eb0695..0a46ac1ea8a 100644
--- a/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java
+++ b/test/jdk/com/sun/net/httpserver/simpleserver/CustomFileSystemTest.java
@@ -256,63 +256,65 @@ public void testDirectoryWithIndexGET(String id,
@Test
public void testNotReadableFileGET() throws Exception {
- if (!Platform.isWindows()) { // not applicable on Windows
- var expectedBody = openHTML + """
-
File not found
-
/aFile.txt
- """ + closeHTML;
- var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
- var root = createDirectoryInCustomFs("testNotReadableFileGET");
- var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE);
-
- file.toFile().setReadable(false, false);
- assert !Files.isReadable(file);
-
- var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
- server.start();
- try {
- var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
- var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build();
- var response = client.send(request, BodyHandlers.ofString());
- assertEquals(response.statusCode(), 404);
- assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
- assertEquals(response.body(), expectedBody);
- } finally {
- server.stop(0);
- file.toFile().setReadable(true, false);
- }
+ if (Platform.isWindows()) {
+ throw new SkipException("Not applicable on Windows");
+ }
+ var expectedBody = openHTML + """
+
File not found
+
/aFile.txt
+ """ + closeHTML;
+ var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
+ var root = createDirectoryInCustomFs("testNotReadableFileGET");
+ var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE);
+
+ file.toFile().setReadable(false, false);
+ assert !Files.isReadable(file);
+
+ var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
+ server.start();
+ try {
+ var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+ var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build();
+ var response = client.send(request, BodyHandlers.ofString());
+ assertEquals(response.statusCode(), 404);
+ assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
+ assertEquals(response.body(), expectedBody);
+ } finally {
+ server.stop(0);
+ file.toFile().setReadable(true, false);
}
}
@Test
public void testNotReadableSegmentGET() throws Exception {
- if (!Platform.isWindows()) { // not applicable on Windows
- var expectedBody = openHTML + """
-
File not found
-
/dir/aFile.txt
- """ + closeHTML;
- var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
- var root = createDirectoryInCustomFs("testNotReadableSegmentGET");
- var dir = Files.createDirectory(root.resolve("dir"));
- var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE);
-
- dir.toFile().setReadable(false, false);
- assert !Files.isReadable(dir);
- assert Files.isReadable(file);
-
- var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
- server.start();
- try {
- var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
- var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build();
- var response = client.send(request, BodyHandlers.ofString());
- assertEquals(response.statusCode(), 404);
- assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
- assertEquals(response.body(), expectedBody);
- } finally {
- server.stop(0);
- dir.toFile().setReadable(true, false);
- }
+ if (Platform.isWindows()) {
+ throw new SkipException("Not applicable on Windows");
+ }
+ var expectedBody = openHTML + """
+
File not found
+
/dir/aFile.txt
+ """ + closeHTML;
+ var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
+ var root = createDirectoryInCustomFs("testNotReadableSegmentGET");
+ var dir = Files.createDirectory(root.resolve("dir"));
+ var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE);
+
+ dir.toFile().setReadable(false, false);
+ assert !Files.isReadable(dir);
+ assert Files.isReadable(file);
+
+ var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
+ server.start();
+ try {
+ var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+ var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build();
+ var response = client.send(request, BodyHandlers.ofString());
+ assertEquals(response.statusCode(), 404);
+ assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
+ assertEquals(response.body(), expectedBody);
+ } finally {
+ server.stop(0);
+ dir.toFile().setReadable(true, false);
}
}
diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java
index ea1c73b361b..167fcd3b5d3 100644
--- a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java
+++ b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java
@@ -309,63 +309,65 @@ public void testDirectoryWithIndexGET(String id,
@Test
public void testNotReadableFileGET() throws Exception {
- if (!Platform.isWindows()) { // not applicable on Windows
- var expectedBody = openHTML + """
-
File not found
-
/aFile.txt
- """ + closeHTML;
- var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
- var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableFileGET"));
- var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE);
+ if (Platform.isWindows()) {
+ throw new SkipException("Not applicable on Windows");
+ }
+ var expectedBody = openHTML + """
+
File not found
+
/aFile.txt
+ """ + closeHTML;
+ var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
+ var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableFileGET"));
+ var file = Files.writeString(root.resolve("aFile.txt"), "some text", CREATE);
- file.toFile().setReadable(false, false);
- assert !Files.isReadable(file);
+ file.toFile().setReadable(false, false);
+ assert !Files.isReadable(file);
- var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
- server.start();
- try {
- var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
- var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build();
- var response = client.send(request, BodyHandlers.ofString());
- assertEquals(response.statusCode(), 404);
- assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
- assertEquals(response.body(), expectedBody);
- } finally {
- server.stop(0);
- file.toFile().setReadable(true, false);
- }
+ var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
+ server.start();
+ try {
+ var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+ var request = HttpRequest.newBuilder(uri(server, "aFile.txt")).build();
+ var response = client.send(request, BodyHandlers.ofString());
+ assertEquals(response.statusCode(), 404);
+ assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
+ assertEquals(response.body(), expectedBody);
+ } finally {
+ server.stop(0);
+ file.toFile().setReadable(true, false);
}
}
@Test
public void testNotReadableSegmentGET() throws Exception {
- if (!Platform.isWindows()) { // not applicable on Windows
- var expectedBody = openHTML + """
-
File not found
-
/dir/aFile.txt
- """ + closeHTML;
- var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
- var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableSegmentGET"));
- var dir = Files.createDirectory(root.resolve("dir"));
- var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE);
+ if (Platform.isWindows()) {
+ throw new SkipException("Not applicable on Windows");
+ }
+ var expectedBody = openHTML + """
+
File not found
+
/dir/aFile.txt
+ """ + closeHTML;
+ var expectedLength = Integer.toString(expectedBody.getBytes(UTF_8).length);
+ var root = Files.createDirectory(TEST_DIR.resolve("testNotReadableSegmentGET"));
+ var dir = Files.createDirectory(root.resolve("dir"));
+ var file = Files.writeString(dir.resolve("aFile.txt"), "some text", CREATE);
- dir.toFile().setReadable(false, false);
- assert !Files.isReadable(dir);
- assert Files.isReadable(file);
+ dir.toFile().setReadable(false, false);
+ assert !Files.isReadable(dir);
+ assert Files.isReadable(file);
- var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
- server.start();
- try {
- var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
- var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build();
- var response = client.send(request, BodyHandlers.ofString());
- assertEquals(response.statusCode(), 404);
- assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
- assertEquals(response.body(), expectedBody);
- } finally {
- server.stop(0);
- dir.toFile().setReadable(true, false);
- }
+ var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE);
+ server.start();
+ try {
+ var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+ var request = HttpRequest.newBuilder(uri(server, "dir/aFile.txt")).build();
+ var response = client.send(request, BodyHandlers.ofString());
+ assertEquals(response.statusCode(), 404);
+ assertEquals(response.headers().firstValue("content-length").get(), expectedLength);
+ assertEquals(response.body(), expectedBody);
+ } finally {
+ server.stop(0);
+ dir.toFile().setReadable(true, false);
}
}
@@ -680,18 +682,22 @@ public void testIllegalPath() throws Exception {
var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO));
assertTrue(iae.getMessage().contains("does not exist"));
}
- { // not readable
- if (!Platform.isWindows()) { // not applicable on Windows
- Path p = Files.createDirectory(TEST_DIR.resolve("aDir"));
- p.toFile().setReadable(false, false);
- assert !Files.isReadable(p);
- try {
- var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO));
- assertTrue(iae.getMessage().contains("not readable"));
- } finally {
- p.toFile().setReadable(true, false);
- }
- }
+ }
+
+ @Test
+ public void testNonReadablePath() throws Exception {
+ if (Platform.isWindows()) {
+ throw new SkipException("Not applicable on Windows");
+ }
+ var addr = LOOPBACK_ADDR;
+ Path p = Files.createDirectory(TEST_DIR.resolve("aDir"));
+ p.toFile().setReadable(false, false);
+ assert !Files.isReadable(p);
+ try {
+ var iae = expectThrows(IAE, () -> SimpleFileServer.createFileServer(addr, p, OutputLevel.INFO));
+ assertTrue(iae.getMessage().contains("not readable"));
+ } finally {
+ p.toFile().setReadable(true, false);
}
}
diff --git a/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java
index 64621796b4f..efcb9c098f0 100644
--- a/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java
+++ b/test/jdk/java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java
@@ -25,7 +25,7 @@
/**
* @test
- * @bug 8346952
+ * @bug 8346952 8361521
* @summary Verifies no exception occurs when triggering updateCG()
* for an ownerless window.
* @key headful
diff --git a/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java b/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java
new file mode 100644
index 00000000000..bb8d7a0ab88
--- /dev/null
+++ b/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * @test
+ * @bug 8369032
+ * @summary Checks the size of the serialized ICC_Profile for standard and
+ * non-standard profiles.
+ */
+public final class SerializedFormSize {
+
+ private static final ICC_Profile[] PROFILES = {
+ ICC_Profile.getInstance(ColorSpace.CS_sRGB),
+ ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB),
+ ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ),
+ ICC_Profile.getInstance(ColorSpace.CS_PYCC),
+ ICC_Profile.getInstance(ColorSpace.CS_GRAY)
+ };
+
+ public static void main(String[] args) throws Exception {
+ for (ICC_Profile profile : PROFILES) {
+ byte[] data = profile.getData();
+ int dataSize = data.length;
+ int min = 3; // At least version, name and data fields
+ int max = 200; // Small enough to confirm no data saved
+
+ // Standard profile: should serialize to a small size, no data
+ test(profile, min, max);
+ // Non-standard profile: includes full data, but only once
+ test(ICC_Profile.getInstance(data), dataSize, dataSize + max);
+ }
+ }
+
+ private static void test(ICC_Profile p, int min, int max) throws Exception {
+ try (var bos = new ByteArrayOutputStream();
+ var oos = new ObjectOutputStream(bos))
+ {
+ oos.writeObject(p);
+ int size = bos.size();
+ if (size < min || size > max) {
+ System.err.println("Expected: >= " + min + " and <= " + max);
+ System.err.println("Actual: " + size);
+ throw new RuntimeException("Wrong size");
+ }
+ }
+ }
+}
diff --git a/test/jdk/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java b/test/jdk/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java
index 6ec6a257ae8..939643c7a45 100644
--- a/test/jdk/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java
+++ b/test/jdk/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java
@@ -23,7 +23,7 @@
/* @test
* @summary Test getGlyphCharIndex() results from layout
- * @bug 8152680
+ * @bug 8152680 8361381
*/
import java.awt.Font;
@@ -40,5 +40,22 @@ public static void main(String[] args) {
if (idx0 != 0) {
throw new RuntimeException("Expected 0, got " + idx0);
}
+
+ // This is the encoding-independent Khmer string "បានស្នើសុំនៅតែត្រូវបានបដិសេធ"
+ // We can't check for more details like e.g. correct line breaking because it is font and platform dependent,
+ // but we can at least chack that the created GlyphVector has monotonically increasing character indices.
+ // This is guaranteed by HarfBuzz's HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS cluster level which is used
+ // in the OpenJDK layout implementation.
+ String khmer = "\u1794\u17b6\u1793\u179f\u17d2\u1793\u17be\u179f\u17bb\u17c6\u1793\u17c5" +
+ "\u178f\u17c2\u178f\u17d2\u179a\u17bc\u179c\u1794\u17b6\u1793\u1794\u178a\u17b7\u179f\u17c1\u1792";
+ font = new Font(Font.DIALOG, Font.PLAIN, 12);
+ gv = font.layoutGlyphVector(frc, khmer.toCharArray(), 0, khmer.length(), 0);
+ int[] indices = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null);
+ for (int i = 0; i < (indices.length - 1); i++) {
+ if (indices[i] > indices[i + 1]) {
+ throw new RuntimeException("Glyph character indices are supposed to be monotonically growing, but character index at position " +
+ i + " is bigger then the one at position " + (i + 1) + ", i.e. " + indices[i] + " > " + indices[i + 1] + ".");
+ }
+ }
}
}
diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java b/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java
new file mode 100644
index 00000000000..855ad1b320b
--- /dev/null
+++ b/test/jdk/java/awt/font/LineBreakMeasurer/KhmerLineBreakTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8361381
+ * @summary GlyphLayout behavior differs on JDK 11+ compared to JDK 8
+ */
+
+import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineBreakMeasurer;
+import java.awt.font.TextAttribute;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.text.BreakIterator;
+import java.util.Locale;
+
+public class KhmerLineBreakTest {
+ static String khmer = "បានស្នើសុំនៅតែត្រូវបានបដិសេធ";
+ /*
+
+ This is part of the output we get from `ExtendedTextSourceLabel::createCharinfo()`
+ when running with `-Dsun.java2d.debugfonts=true`. It's a listing of the 28 code points
+ of the `khmer` string defined above and displays their x-position during rendering as
+ well as their advance. Code points with zero advance belong to the glyph cluster which
+ is started by the first preceding code point with a non-zero advance. There should be no
+ breaks at characters with zero advance, because this would break a glyph cluster.
+
+ 0 ch: 1794 x: 0.0 xa: 68.115234
+ 1 ch: 17b6 x: 68.115234 xa: 0.0
+ 2 ch: 1793 x: 68.115234 xa: 45.410156
+ 3 ch: 179f x: 113.52539 xa: 90.82031
+ 4 ch: 17d2 x: 204.3457 xa: 0.0
+ 5 ch: 1793 x: 204.3457 xa: 0.0
+ 6 ch: 17be x: 204.3457 xa: 0.0
+ 7 ch: 179f x: 204.3457 xa: 68.115234
+ 8 ch: 17bb x: 272.46094 xa: 0.0
+ 9 ch: 17c6 x: 272.46094 xa: 0.0
+ 10 ch: 1793 x: 272.46094 xa: 90.82031
+ 11 ch: 17c5 x: 363.28125 xa: 0.0
+ 12 ch: 178f x: 363.28125 xa: 68.115234
+ 13 ch: 17c2 x: 431.39648 xa: 0.0
+ 14 ch: 178f x: 431.39648 xa: 68.115234
+ 15 ch: 17d2 x: 499.51172 xa: 0.0
+ 16 ch: 179a x: 499.51172 xa: 0.0
+ 17 ch: 17bc x: 499.51172 xa: 0.0
+ 18 ch: 179c x: 499.51172 xa: 22.705078
+ 19 ch: 1794 x: 522.2168 xa: 68.115234
+ 20 ch: 17b6 x: 590.33203 xa: 0.0
+ 21 ch: 1793 x: 590.33203 xa: 45.410156
+ 22 ch: 1794 x: 635.7422 xa: 45.410156
+ 23 ch: 178a x: 681.15234 xa: 45.410156
+ 24 ch: 17b7 x: 726.5625 xa: 0.0
+ 25 ch: 179f x: 726.5625 xa: 90.82031
+ 26 ch: 17c1 x: 817.3828 xa: 0.0
+ 27 ch: 1792 x: 817.3828 xa: 45.410156
+
+ */
+ static boolean[] possibleBreak = new boolean[]
+ { true, false, true, true, false, false, false, true, false, false,
+ true, false, true, false, true, false, false, false, true, true,
+ false, true, true, true, false, true, false, true, true /* */ };
+ static Locale locale = new Locale.Builder().setLanguage("km").setRegion("KH").build();
+ static BreakIterator breakIterator = BreakIterator.getLineInstance(locale);
+ static FontRenderContext frc = new FontRenderContext(null, true, true);
+
+ public static void main(String[] args) {
+ Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
+ for (int i=0; i < allFonts.length; i++) {
+ if (allFonts[i].canDisplayUpTo(khmer) == -1) {
+ Font font = allFonts[i].deriveFont(Font.PLAIN, 60f);
+ System.out.println("Trying font: " + font.getFontName());
+ AttributedString attrStr = new AttributedString(khmer);
+ attrStr.addAttribute(TextAttribute.FONT, font);
+ AttributedCharacterIterator it = attrStr.getIterator();
+ for (int width = 200; width < 400; width += 10) {
+ LineBreakMeasurer measurer = new LineBreakMeasurer(it, breakIterator, frc);
+ System.out.print(width + " : ");
+ while (measurer.getPosition() < it.getEndIndex()) {
+ int nextOffset = measurer.nextOffset(width);
+ System.out.print(nextOffset + " ");
+ if (!possibleBreak[nextOffset]) {
+ System.out.println();
+ throw new RuntimeException("Invalid break at offset " + nextOffset + " (width = " + width + " font = " + font.getFontName() + ")");
+ }
+ measurer.setPosition(nextOffset);
+ }
+ System.out.println();
+ }
+ System.out.println("OK");
+ }
+ }
+ }
+}
diff --git a/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java b/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java
deleted file mode 100644
index a12fd802fd5..00000000000
--- a/test/jdk/java/awt/font/TextLayout/TestLayoutVsICU.java
+++ /dev/null
@@ -1,889 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-
-/*
- * Copyright (C) 2013-2014 IBM Corporation and Others. All Rights Reserved.
- */
-
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Font;
-import java.awt.FontFormatException;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
-import java.awt.Image;
-import java.awt.Paint;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.RenderingHints.Key;
-import java.awt.Shape;
-import java.awt.Stroke;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ImageObserver;
-import java.awt.image.RenderedImage;
-import java.awt.image.renderable.RenderableImage;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.AttributedCharacterIterator;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.TreeMap;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-/**
- * This test runs against a test XML file. It opens the fonts and attempts
- * to shape and layout glyphs.
- * Note that the test is highly environment dependent- you must have
- * the same versions of the same fonts available or the test will fail.
- *
- * It is similar to letest which is part of ICU.
- * For reference, here are some reference items:
- * ICU's test file:
- * http://source.icu-project.org/repos/icu/icu/trunk/source/test/testdata/letest.xml
- * ICU's readme for the similar test:
- * http://source.icu-project.org/repos/icu/icu/trunk/source/test/letest/readme.html
- *
- * @bug 8054203
- * @test
- * @summary manual test of layout engine behavior. Takes an XML control file.
- * @compile TestLayoutVsICU.java
- * @author srl
- * @run main/manual
- */
-public class TestLayoutVsICU {
-
- public static boolean OPT_DRAW = false;
- public static boolean OPT_VERBOSE = false;
- public static boolean OPT_FAILMISSING = false;
- public static boolean OPT_NOTHROW= false; // if true - don't stop on failure
-
- public static int docs = 0; // # docs processed
- public static int skipped = 0; // cases skipped due to bad font
- public static int total = 0; // cases processed
- public static int bad = 0; // cases with errs
-
- public static final String XML_LAYOUT_TESTS = "layout-tests"; // top level
- public static final String XML_TEST_CASE = "test-case";
- public static final String XML_TEST_FONT = "test-font";
- public static final String XML_TEST_TEXT = "test-text";
- public static final String XML_RESULT_GLYPHS = "result-glyphs";
- public static final String XML_ID = "id";
- public static final String XML_SCRIPT = "script";
- public static final String XML_NAME = "name";
- public static final String XML_VERSION = "version";
- public static final String XML_CHECKSUM = "checksum";
- public static final String XML_RESULT_INDICES = "result-indices";
- public static final String XML_RESULT_POSITIONS = "result-positions";
-
- /**
- * @param args
- * @throws IOException
- * @throws SAXException
- * @throws ParserConfigurationException
- */
- public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
- System.out.println("Java " + System.getProperty("java.version") + " from " + System.getProperty("java.vendor"));
- TestLayoutVsICU tlvi = null;
- for(String arg : args) {
- if(arg.equals("-d")) {
- OPT_DRAW = true;
- } else if(arg.equals("-n")) {
- OPT_NOTHROW = true;
- } else if(arg.equals("-v")) {
- OPT_VERBOSE = true;
- } else if(arg.equals("-f")) {
- OPT_FAILMISSING = true;
- } else {
- if(tlvi == null) {
- tlvi = new TestLayoutVsICU();
- }
- try {
- tlvi.show(arg);
- } finally {
- if(OPT_VERBOSE) {
- System.out.println("# done with " + arg);
- }
- }
- }
- }
-
- if(tlvi == null) {
- throw new IllegalArgumentException("No XML input. Usage: " + TestLayoutVsICU.class.getSimpleName() + " [-d][-v][-f] letest.xml ...");
- } else {
- System.out.println("\n\nRESULTS:\n");
- System.out.println(skipped+"\tskipped due to missing font");
- System.out.println(total+"\ttested of which:");
- System.out.println(bad+"\twere bad");
-
- if(bad>0) {
- throw new InternalError("One or more failure(s)");
- }
- }
- }
-
- String id;
-
- private void show(String arg) throws ParserConfigurationException, SAXException, IOException {
- id = "";
- File xmlFile = new File(arg);
- if(!xmlFile.exists()) {
- throw new FileNotFoundException("Can't open input XML file " + arg);
- }
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- DocumentBuilder db = dbf.newDocumentBuilder();
- if(OPT_VERBOSE) {
- System.out.println("# Parsing " + xmlFile.getAbsolutePath());
- }
- Document doc = db.parse(xmlFile);
- Element e = doc.getDocumentElement();
- if(!XML_LAYOUT_TESTS.equals(e.getNodeName())) {
- throw new IllegalArgumentException("Document " + xmlFile.getAbsolutePath() + " does not have as its base");
- }
-
- NodeList testCases = e.getElementsByTagName(XML_TEST_CASE);
- for(int caseNo=0;caseNo testCaseAttrs = attrs(testCase);
- id = testCaseAttrs.get(XML_ID);
- final String script = testCaseAttrs.get(XML_SCRIPT);
- String testText = null;
- Integer[] expectGlyphs = null;
- Integer[] expectIndices = null;
- Map fontAttrs = null;
- if(OPT_VERBOSE) {
- System.out.println("#"+caseNo+" id="+id + ", script="+script);
- }
- NodeList children = testCase.getChildNodes();
- for(int sub=0;sub glyphs = new ArrayList();
- Graphics2D myg2 = new Graphics2D(){
-
- @Override
- public void draw(Shape s) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean drawImage(Image img, AffineTransform xform,
- ImageObserver obs) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void drawImage(BufferedImage img,
- BufferedImageOp op, int x, int y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawRenderedImage(RenderedImage img,
- AffineTransform xform) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawRenderableImage(RenderableImage img,
- AffineTransform xform) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawString(String str, int x, int y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawString(String str, float x, float y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawString(
- AttributedCharacterIterator iterator, int x, int y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawString(
- AttributedCharacterIterator iterator, float x,
- float y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawGlyphVector(GlyphVector g, float x, float y) {
- if(x!=0.0 || y!=0.0) {
- throw new InternalError("x,y should be 0 but got " + x+","+y);
- }
- //System.err.println("dGV : " + g.toString() + " @ "+x+","+y);
- glyphs.add(g);
- }
-
- @Override
- public void fill(Shape s) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public GraphicsConfiguration getDeviceConfiguration() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setComposite(Composite comp) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setPaint(Paint paint) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setStroke(Stroke s) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setRenderingHint(Key hintKey, Object hintValue) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Object getRenderingHint(Key hintKey) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setRenderingHints(Map, ?> hints) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void addRenderingHints(Map, ?> hints) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public RenderingHints getRenderingHints() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void translate(int x, int y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void translate(double tx, double ty) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void rotate(double theta) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void rotate(double theta, double x, double y) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void scale(double sx, double sy) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void shear(double shx, double shy) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void transform(AffineTransform Tx) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setTransform(AffineTransform Tx) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public AffineTransform getTransform() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Paint getPaint() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Composite getComposite() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setBackground(Color color) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Color getBackground() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Stroke getStroke() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void clip(Shape s) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public FontRenderContext getFontRenderContext() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Graphics create() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Color getColor() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setColor(Color c) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setPaintMode() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setXORMode(Color c1) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Font getFont() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setFont(Font font) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public FontMetrics getFontMetrics(Font f) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Rectangle getClipBounds() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void clipRect(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setClip(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Shape getClip() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setClip(Shape clip) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void copyArea(int x, int y, int width, int height,
- int dx, int dy) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawLine(int x1, int y1, int x2, int y2) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void fillRect(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void clearRect(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawRoundRect(int x, int y, int width,
- int height, int arcWidth, int arcHeight) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void fillRoundRect(int x, int y, int width,
- int height, int arcWidth, int arcHeight) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawOval(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void fillOval(int x, int y, int width, int height) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawArc(int x, int y, int width, int height,
- int startAngle, int arcAngle) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void fillArc(int x, int y, int width, int height,
- int startAngle, int arcAngle) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawPolyline(int[] xPoints, int[] yPoints,
- int nPoints) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void drawPolygon(int[] xPoints, int[] yPoints,
- int nPoints) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void fillPolygon(int[] xPoints, int[] yPoints,
- int nPoints) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean drawImage(Image img, int x, int y,
- ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean drawImage(Image img, int x, int y,
- int width, int height, ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean drawImage(Image img, int x, int y,
- Color bgcolor, ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean drawImage(Image img, int x, int y,
- int width, int height, Color bgcolor,
- ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean drawImage(Image img, int dx1, int dy1,
- int dx2, int dy2, int sx1, int sy1, int sx2,
- int sy2, ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean drawImage(Image img, int dx1, int dy1,
- int dx2, int dy2, int sx1, int sy1, int sx2,
- int sy2, Color bgcolor, ImageObserver observer) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void dispose() {
- // TODO Auto-generated method stub
-
- }
-
- };
- tl.draw(myg2, 0, 0);
- if(glyphs.size() != 1) {
- err("drew " + glyphs.size() + " times - expected 1");
- total++;
- bad++;
- continue;
- }
- boolean isBad = false;
- GlyphVector gv = glyphs.get(0);
-
- // GLYPHS
- int gotGlyphs[] = gv.getGlyphCodes(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]);
-
- int count = Math.min(gotGlyphs.length, expectGlyphs.length); // go up to this count
-
- for(int i=0;i> OK: " + gotGlyphs.length + " glyphs");
- }
- }
-
-
- if(isBad) {
- bad++;
- System.out.println("* FAIL: " + id + " /\t" + fontName);
- } else {
- System.out.println("* OK : " + id + " /\t" + fontName);
- }
- total++;
- }
- }
-
-
- private boolean verifyFont(File f, Map fontAttrs) {
- InputStream fis = null;
- String fontName = fontAttrs.get(XML_NAME);
- int count=0;
- try {
- fis = new BufferedInputStream(new FileInputStream(f));
-
- int i = 0;
- int r;
- try {
- while((r=fis.read())!=-1) {
- i+=(int)r;
- count++;
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- if(OPT_VERBOSE) {
- System.out.println("for " + f.getAbsolutePath() + " chks = 0x" + Integer.toHexString(i) + " size=" + count);
- }
- String theirStr = fontAttrs.get("rchecksum");
-
- String ourStr = Integer.toHexString(i).toLowerCase();
-
- if(theirStr!=null) {
- if(theirStr.startsWith("0x")) {
- theirStr = theirStr.substring(2).toLowerCase();
- } else {
- theirStr = theirStr.toLowerCase();
- }
- long theirs = Integer.parseInt(theirStr, 16);
- if(theirs != i) {
- err("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but file said " + theirs +" (0x"+theirStr+") - perhaps a different font?");
- return false;
- } else {
- if(OPT_VERBOSE) {
- System.out.println(" rchecksum for " + fontName + " OK");
- }
- return true;
- }
- } else {
- //if(OPT_VERBOSE) {
- System.err.println("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but rchecksum was MISSING. Old ICU data?");
- //}
- }
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- } finally {
- try {
- fis.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return true;
- }
-
-
- private Integer[] parseHexArray(String hex) {
- List ret = new ArrayList();
- String items[] = hex.split("[\\s,]");
- for(String i : items) {
- if(i.isEmpty()) continue;
- if(i.startsWith("0x")) {
- i = i.substring(2);
- }
- ret.add(Integer.parseInt(i, 16));
- }
- return ret.toArray(new Integer[0]);
- }
-
-
- private void err(String string) {
- if(OPT_NOTHROW) {
- System.out.println(id+" ERROR: " + string +" (continuing due to -n)");
- } else {
- throw new InternalError(id+ ": " + string);
- }
- }
-
-
- private Font getFont(String fontName, Map fontAttrs) {
- Font f;
- if(false)
- try {
- f = Font.getFont(fontName);
- if(f!=null) {
- if(OPT_VERBOSE) {
- System.out.println("Loaded default path to " + fontName);
- }
- return f;
- }
- } catch(Throwable t) {
- if(OPT_VERBOSE) {
- t.printStackTrace();
- System.out.println("problem loading font " + fontName + " - " + t.toString());
- }
- }
-
- File homeDir = new File(System.getProperty("user.home"));
- File fontDir = new File(homeDir, "fonts");
- File fontFile = new File(fontDir, fontName);
- //System.out.println("## trying " + fontFile.getAbsolutePath());
- if(fontFile.canRead()) {
- try {
- if(!verifyFont(fontFile,fontAttrs)) {
- System.out.println("Warning: failed to verify " + fontName);
- }
- f = Font.createFont(Font.TRUETYPE_FONT, fontFile);
- if(f!=null & OPT_VERBOSE) {
- System.out.println("> loaded from " + fontFile.getAbsolutePath() + " - " + f.toString());
- }
- return f;
- } catch (FontFormatException e) {
- if(OPT_VERBOSE) {
- e.printStackTrace();
- System.out.println("problem loading font " + fontName + " - " + e.toString());
- }
- } catch (IOException e) {
- if(OPT_VERBOSE) {
- e.printStackTrace();
- System.out.println("problem loading font " + fontName + " - " + e.toString());
- }
- }
- }
- return null;
- }
-
-
- private static Map attrs(Node testCase) {
- Map rv = new TreeMap();
- NamedNodeMap nnm = testCase.getAttributes();
- for(int i=0;i
-
-
-
-
-
-
-
-
-
- श्रीमद् भगवद्गीता अध्याय अर्जुन विषाद योग धृतराष्ट्र उवाचृ धर्मक्षेत्रे कुरुक्षेत्रे समवेता युयुत्सवः मामकाः पाण्डवाश्चैव किमकुर्वत संजव
-
-
- 0x0000009E, 0x0000009A, 0x00000051, 0x00000222, 0x00000098, 0x00000091, 0x00000051, 0x00000003,
- 0x00000097, 0x00000082, 0x0000009D, 0x000001A5, 0x0000FFFF, 0x0000FFFF, 0x00000222, 0x0000008F,
- 0x00000221, 0x00000003, 0x0000005C, 0x000000DA, 0x0000FFFF, 0x00000099, 0x00000221, 0x00000099,
- 0x00000003, 0x0000005C, 0x00000087, 0x000001D5, 0x0000005B, 0x0000FFFF, 0x00000093, 0x00000003,
- 0x000001D2, 0x0000009D, 0x0000009F, 0x00000221, 0x00000091, 0x00000003, 0x00000099, 0x0000022A,
- 0x00000082, 0x00000003, 0x00000092, 0x000001D9, 0x0000008F, 0x0000009A, 0x00000221, 0x000001B4,
- 0x0000FFFF, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000003, 0x00000060, 0x0000009D, 0x00000221,
- 0x00000085, 0x000001D9, 0x00000003, 0x00000092, 0x00000098, 0x0000005B, 0x0000FFFF, 0x000000A2,
- 0x0000FFFF, 0x0000FFFF, 0x0000022F, 0x0000008F, 0x0000009A, 0x00000051, 0x0000022F, 0x00000003,
- 0x00000080, 0x000001D5, 0x0000009A, 0x000001FD, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x0000022F,
- 0x0000008F, 0x0000009A, 0x00000051, 0x0000022F, 0x00000003, 0x000000A0, 0x00000098, 0x0000009D,
- 0x0000022F, 0x0000008F, 0x00000221, 0x00000003, 0x00000099, 0x000001D5, 0x00000099, 0x000001D5,
- 0x000000D7, 0x0000FFFF, 0x000000A0, 0x0000009D, 0x0000022C, 0x00000003, 0x00000098, 0x00000221,
- 0x00000098, 0x00000080, 0x00000221, 0x0000022C, 0x00000003, 0x00000094, 0x00000221, 0x000000D6,
- 0x0000FFFF, 0x0000008C, 0x0000009D, 0x00000221, 0x000001B1, 0x0000FFFF, 0x0000FFFF, 0x00000230,
- 0x0000009D, 0x00000003, 0x000001D1, 0x00000080, 0x00000098, 0x00000080, 0x000001D5, 0x0000009D,
- 0x0000005B, 0x0000FFFF, 0x0000008F, 0x00000003, 0x000000A0, 0x00000232, 0x00000087, 0x0000009D
-
-
-
- 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019, 0x0000001C, 0x0000001D, 0x0000001A, 0x0000001B, 0x0000001E, 0x0000001F,
- 0x00000021, 0x00000020, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027,
- 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F,
- 0x00000030, 0x00000031, 0x00000033, 0x00000032, 0x00000034, 0x00000035, 0x00000036, 0x00000037,
- 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003E, 0x0000003C, 0x0000003D, 0x0000003F,
- 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000045, 0x00000044, 0x00000046, 0x00000047,
- 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F,
- 0x00000050, 0x00000052, 0x00000051, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057,
- 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F,
- 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067,
- 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F,
- 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077,
- 0x00000078, 0x00000079, 0x0000007B, 0x0000007A, 0x0000007C, 0x0000007D, 0x0000007E, 0x00000081,
- 0x0000007F, 0x00000080, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087
-
-
-
- 0.000000, 0.000000, 9.468750, 0.000000, 19.130859, -0.451172, 15.984375, 0.000000,
- 19.640625, 0.000000, 29.109375, 0.000000, 40.177734, -0.451172, 37.078125, 0.000000,
- 43.078125, 0.000000, 52.546875, 0.000000, 62.015625, 0.000000, 69.984375, 0.000000,
- 77.953125, 0.000000, 77.953125, 0.000000, 77.953125, 0.000000, 81.609375, 0.000000,
- 89.578125, 0.000000, 93.234375, 0.000000, 99.234375, 0.000000, 109.171875, 0.000000,
- 116.437500, 0.000000, 116.437500, 0.000000, 125.906250, 0.000000, 129.562500, 0.000000,
- 139.031250, 0.000000, 145.031250, 0.000000, 154.968750, 0.000000, 164.718750, -0.011719,
- 164.718750, 0.263672, 164.437500, 0.000000, 164.437500, 0.000000, 173.906250, 0.000000,
- 179.906250, 0.000000, 184.265625, 0.000000, 192.234375, 0.000000, 200.203125, 0.000000,
- 203.859375, 0.000000, 211.828125, 0.000000, 217.828125, 0.000000, 227.296875, 0.000000,
- 231.375000, 0.000000, 240.843750, 0.000000, 246.843750, 0.000000, 256.740234, -0.011719,
- 256.312500, 0.000000, 264.281250, 0.000000, 270.796875, 0.000000, 274.453125, 0.000000,
- 282.796875, 0.000000, 282.796875, 0.000000, 282.796875, 0.000000, 292.458984, -0.451172,
- 289.312500, 0.000000, 295.312500, 0.000000, 303.281250, 0.000000, 311.250000, 0.000000,
- 314.906250, 0.000000, 324.890625, -0.011719, 324.375000, 0.000000, 330.375000, 0.000000,
- 339.843750, 0.000000, 349.675781, 0.263672, 349.312500, 0.000000, 349.312500, 0.000000,
- 360.187500, 0.000000, 360.187500, 0.000000, 359.384766, 0.275391, 360.187500, 0.000000,
- 368.156250, 0.000000, 377.818359, -0.451172, 372.996094, 0.263672, 374.671875, 0.000000,
- 380.671875, 0.000000, 388.371094, -0.011719, 391.546875, 0.000000, 398.062500, 0.000000,
- 399.421875, 0.000000, 410.296875, 0.000000, 410.296875, 0.000000, 409.494141, 0.275391,
- 410.296875, 0.000000, 418.265625, 0.000000, 427.927734, -0.451172, 423.105469, 0.263672,
- 424.781250, 0.000000, 430.781250, 0.000000, 440.250000, 0.000000, 449.718750, 0.000000,
- 456.832031, 0.263672, 457.687500, 0.000000, 465.656250, 0.000000, 469.312500, 0.000000,
- 475.312500, 0.000000, 484.921875, -0.011719, 484.781250, 0.000000, 494.390625, -0.011719,
- 494.250000, 0.000000, 500.179688, 0.000000, 500.179688, 0.000000, 509.648438, 0.000000,
- 517.617188, 0.000000, 521.976562, 0.000000, 527.976562, 0.000000, 537.445312, 0.000000,
- 541.101562, 0.000000, 550.570312, 0.000000, 561.445312, 0.000000, 565.101562, 0.000000,
- 569.460938, 0.000000, 575.460938, 0.000000, 583.429688, 0.000000, 587.085938, 0.000000,
- 594.351562, 0.000000, 594.351562, 0.000000, 602.320312, 0.000000, 610.289062, 0.000000,
- 613.945312, 0.000000, 624.820312, 0.000000, 624.820312, 0.000000, 624.691406, 0.263672,
- 624.820312, 0.000000, 632.789062, 0.000000, 638.789062, 0.000000, 643.148438, 0.000000,
- 654.023438, 0.000000, 663.492188, 0.000000, 671.191406, -0.011719, 674.367188, 0.000000,
- 682.628906, 0.263672, 682.335938, 0.000000, 682.335938, 0.000000, 690.304688, 0.000000,
- 696.304688, 0.000000, 705.140625, 0.439453, 705.773438, 0.000000, 715.242188, 0.000000,
- 723.210938, 0.000000
-
-
-
-
-
-
- أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية
-
-
- 0x0000CE28, 0x0000CE87, 0x0000CE41, 0x0000CE81, 0x0000CE42, 0x0000CE54, 0x0000CE73, 0x0000CE21,
- 0x00000003, 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE73, 0x0000CE21,
- 0x00000003, 0x0000CE5E, 0x0000CE88, 0x0000CE78, 0x0000CE33, 0x00000003, 0x0000CE84, 0x0000CE74,
- 0x0000CE5F, 0x00000003, 0x0000CE85, 0x0000CE82, 0x0000CE2C, 0x0000CE38, 0x0000CE87, 0x00000003,
- 0x0000CE3E, 0x0000CE37, 0x0000CE21, 0x0000CE81, 0x00000003, 0x0000CE42, 0x0000CE88, 0x0000CE68,
- 0x0000CE4C, 0x0000CE2B, 0x00000003, 0x0000CE75, 0x0000CE22, 0x0000CE5C, 0x0000CE7B, 0x00000003,
- 0x0000CE3E, 0x0000CE33, 0x0000CE82, 0x0000CE87, 0x00000003, 0x0000CE76, 0x0000CE73, 0x0000CE81,
- 0x00000003, 0x00000588, 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE74,
- 0x0000CE73, 0x00000003, 0x0000CE75, 0x0000CE22, 0x0000CE6B, 0x0000CE41, 0x0000FFFE, 0x0000CE8B,
- 0x0000CE21, 0x00000003, 0x0000CE7D, 0x0000CE40, 0x0000CE7F, 0x00000003, 0x0000CE4E, 0x0000CE88,
- 0x0000CE50, 0x0000CE3C, 0x0000CE2B, 0x0000CE81, 0x00000003, 0x0000CE42, 0x0000CE88, 0x0000CE68,
- 0x0000CE4C, 0x0000CE2C, 0x0000CE74, 0x0000CE73, 0x00000003, 0x0000CE28, 0x0000CE78, 0x0000CE5C,
- 0x0000CE7B, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, 0x0000CE29, 0x0000CE22, 0x0000CE20,
- 0x0000CE77, 0x00000003, 0x0000CE6D, 0x0000CE22, 0x0000CE7C, 0x0000CE7F, 0x00000003, 0x0000CE79,
- 0x0000CE22, 0x0000CE6F, 0x00000003, 0x00000588, 0x00000005, 0x0000CE3D, 0x0000CE82, 0x0000CE70,
- 0x000005B5, 0x0000CE7B, 0x0000CE82, 0x0000CE87, 0x00000005, 0x00000003, 0x0000CE5D, 0x0000CE21,
- 0x0000CE42, 0x0000CE2C, 0x0000CE3B, 0x0000CE21, 0x00000003, 0x0000CE72, 0x0000CE26, 0x0000CE6B,
- 0x0000CE81, 0x00000003, 0x00000011, 0x0000CE22, 0x0000CE80, 0x0000CE7C, 0x0000CE77, 0x00000003,
- 0x0000CE3E, 0x0000CE37, 0x0000CE21, 0x0000CE81, 0x00000003, 0x0000CE72, 0x0000CE70, 0x0000CE73,
- 0x00000003, 0x0000CE22, 0x0000CE7C, 0x0000CE88, 0x0000CE60, 0x0000CE77, 0x00000003, 0x0000CE22,
- 0x0000CE78, 0x0000CE6B, 0x0000CE41, 0x00000003, 0x0000CE86, 0x0000CE58, 0x0000CE60, 0x000005B4,
- 0x0000CE2B, 0x00000003, 0x0000CE79, 0x0000CE17, 0x00000003, 0x0000CE3E, 0x0000CE60, 0x0000CE25,
- 0x00000003, 0x0000CE83, 0x0000CE42, 0x0000CE3B, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003,
- 0x0000CE65, 0x0000CE41, 0x0000CE22, 0x0000CE38, 0x0000CE78, 0x0000CE73, 0x0000CE21, 0x0000CE81,
- 0x00000003, 0x0000CE65, 0x0000CE42, 0x0000CE37, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003,
- 0x0000CE7A, 0x0000CE87, 0x0000CE44, 0x0000CE3C, 0x0000CE2C, 0x0000CE25, 0x00000003, 0x0000CE75,
- 0x0000CE82, 0x0000CE6C, 0x0000CE2B, 0x0000CE81, 0x00000003, 0x00000588, 0x0000CE75, 0x0000CE22,
- 0x0000CE6B, 0x0000CE41, 0x0000FFFE, 0x0000CE8B, 0x0000CE21, 0x00000003, 0x0000CE5E, 0x0000CE77,
- 0x00000003, 0x0000CE56, 0x0000CE6C, 0x0000CE67, 0x00000003, 0x0000CE24, 0x0000CE88, 0x0000CE47,
- 0x0000CE21, 0x0000CE82, 0x0000CE38, 0x0000CE73, 0x0000CE21, 0x00000003, 0x0000CE72, 0x0000CE77,
- 0x0000CE22, 0x0000CE60, 0x0000CE2C, 0x0000CE2B, 0x00000003, 0x00000588, 0x0000CE22, 0x000005B0,
- 0x0000CE47, 0x0000CE22, 0x0000CE47, 0x0000CE17
-
-
-
- 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4,
- 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC,
- 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4,
- 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC,
- 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4,
- 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC,
- 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4,
- 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC,
- 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4,
- 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC,
- 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4,
- 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C,
- 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094,
- 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C,
- 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084,
- 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C,
- 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074,
- 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C,
- 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064,
- 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C,
- 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054,
- 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C,
- 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044,
- 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C,
- 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034,
- 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C,
- 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
- 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C,
- 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014,
- 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C,
- 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004,
- 0x00000003, 0x00000002, 0x00000001, 0x00000000
-
-
-
- 0.000000, 0.000000, 4.007812, 0.000000, 8.226562, 0.000000, 12.679688, 0.000000,
- 18.679688, 0.000000, 23.132812, 0.000000, 31.289062, 0.000000, 34.312500, 0.000000,
- 36.375000, 0.000000, 41.062500, 0.000000, 50.296875, 0.000000, 54.750000, 0.000000,
- 56.859375, 0.000000, 62.367188, 0.000000, 66.632812, 0.000000, 69.656250, 0.000000,
- 71.718750, 0.000000, 76.406250, 0.000000, 81.421875, 0.000000, 85.664062, 0.000000,
- 89.929688, 0.000000, 95.742188, 0.000000, 100.429688, 0.000000, 108.796875, 0.000000,
- 112.171875, 0.000000, 115.734375, 0.000000, 120.421875, 0.000000, 128.765625, 0.000000,
- 134.765625, 0.000000, 139.007812, 0.000000, 144.515625, 0.000000, 148.734375, 0.000000,
- 153.421875, 0.000000, 157.359375, 0.000000, 163.171875, 0.000000, 165.234375, 0.000000,
- 171.234375, 0.000000, 175.921875, 0.000000, 180.375000, 0.000000, 184.617188, 0.000000,
- 188.085938, 0.000000, 195.117188, 0.000000, 199.312500, 0.000000, 204.000000, 0.000000,
- 208.007812, 0.000000, 210.117188, 0.000000, 217.054688, 0.000000, 220.429688, 0.000000,
- 225.117188, 0.000000, 229.054688, 0.000000, 234.867188, 0.000000, 240.867188, 0.000000,
- 245.085938, 0.000000, 249.773438, 0.000000, 253.781250, 0.000000, 256.804688, 0.000000,
- 262.804688, 0.000000, 267.492188, 0.000000, 271.007812, 0.000000, 280.242188, 0.000000,
- 284.695312, 0.000000, 286.804688, 0.000000, 292.312500, 0.000000, 296.578125, 0.000000,
- 299.953125, 0.000000, 302.976562, 0.000000, 307.664062, 0.000000, 311.671875, 0.000000,
- 313.781250, 0.000000, 317.882812, 0.000000, 322.335938, 0.000000, 322.335938, 0.000000,
- 328.500000, 0.000000, 330.562500, 0.000000, 335.250000, 0.000000, 339.140625, 0.000000,
- 343.078125, 0.000000, 348.984375, 0.000000, 353.671875, 0.000000, 366.445312, 0.000000,
- 370.687500, 0.000000, 378.843750, 0.000000, 384.351562, 0.000000, 388.546875, 0.000000,
- 394.546875, 0.000000, 399.234375, 0.000000, 403.687500, 0.000000, 407.929688, 0.000000,
- 411.398438, 0.000000, 418.429688, 0.000000, 422.671875, 0.000000, 426.046875, 0.000000,
- 429.070312, 0.000000, 433.757812, 0.000000, 437.765625, 0.000000, 442.031250, 0.000000,
- 448.968750, 0.000000, 452.343750, 0.000000, 452.343750, 0.000000, 458.507812, 0.000000,
- 460.570312, 0.000000, 465.257812, 0.000000, 474.492188, 0.000000, 476.601562, 0.000000,
- 480.843750, 0.000000, 485.109375, 0.000000, 489.796875, 0.000000, 497.437500, 0.000000,
- 499.546875, 0.000000, 503.765625, 0.000000, 509.671875, 0.000000, 514.359375, 0.000000,
- 521.671875, 0.000000, 523.781250, 0.000000, 529.453125, 0.000000, 534.140625, 0.000000,
- 537.656250, 0.000000, 543.046875, 0.000000, 546.585938, 0.000000, 552.585938, 0.000000,
- 560.367188, 0.000000, 560.367188, 0.000000, 563.742188, 0.000000, 569.742188, 0.000000,
- 573.960938, 0.000000, 579.351562, 0.000000, 584.039062, 0.000000, 589.851562, 0.000000,
- 591.914062, 0.000000, 596.367188, 0.000000, 600.609375, 0.000000, 606.421875, 0.000000,
- 608.484375, 0.000000, 613.171875, 0.000000, 619.570312, 0.000000, 623.812500, 0.000000,
- 627.914062, 0.000000, 633.914062, 0.000000, 638.601562, 0.000000, 641.929688, 0.000000,
- 644.039062, 0.000000, 647.789062, 0.000000, 652.007812, 0.000000, 656.273438, 0.000000,
- 660.960938, 0.000000, 664.898438, 0.000000, 670.710938, 0.000000, 672.773438, 0.000000,
- 678.773438, 0.000000, 683.460938, 0.000000, 689.859375, 0.000000, 697.640625, 0.000000,
- 700.664062, 0.000000, 705.351562, 0.000000, 707.460938, 0.000000, 711.679688, 0.000000,
- 715.921875, 0.000000, 719.390625, 0.000000, 723.656250, 0.000000, 728.343750, 0.000000,
- 730.453125, 0.000000, 734.718750, 0.000000, 738.820312, 0.000000, 743.273438, 0.000000,
- 747.960938, 0.000000, 756.328125, 0.000000, 763.265625, 0.000000, 766.734375, 0.000000,
- 766.734375, 0.000000, 770.929688, 0.000000, 775.617188, 0.000000, 782.929688, 0.000000,
- 785.273438, 0.000000, 789.960938, 0.000000, 793.898438, 0.000000, 797.367188, 0.000000,
- 800.812500, 0.000000, 805.500000, 0.000000, 813.843750, 0.000000, 818.296875, 0.000000,
- 824.109375, 0.000000, 824.109375, 0.000000, 830.273438, 0.000000, 832.335938, 0.000000,
- 837.023438, 0.000000, 846.257812, 0.000000, 850.710938, 0.000000, 852.820312, 0.000000,
- 858.328125, 0.000000, 862.593750, 0.000000, 865.617188, 0.000000, 867.679688, 0.000000,
- 873.679688, 0.000000, 878.367188, 0.000000, 887.601562, 0.000000, 892.054688, 0.000000,
- 897.867188, 0.000000, 897.867188, 0.000000, 904.031250, 0.000000, 906.093750, 0.000000,
- 910.781250, 0.000000, 918.257812, 0.000000, 922.476562, 0.000000, 926.929688, 0.000000,
- 932.437500, 0.000000, 936.679688, 0.000000, 940.125000, 0.000000, 944.812500, 0.000000,
- 948.820312, 0.000000, 954.820312, 0.000000, 958.289062, 0.000000, 962.484375, 0.000000,
- 968.484375, 0.000000, 973.171875, 0.000000, 976.687500, 0.000000, 980.695312, 0.000000,
- 982.804688, 0.000000, 986.906250, 0.000000, 991.359375, 0.000000, 991.359375, 0.000000,
- 997.523438, 0.000000, 999.585938, 0.000000, 1004.273438, 0.000000, 1009.289062, 0.000000,
- 1013.554688, 0.000000, 1018.242188, 0.000000, 1026.187500, 0.000000, 1029.656250, 0.000000,
- 1033.757812, 0.000000, 1038.445312, 0.000000, 1047.796875, 0.000000, 1052.039062, 0.000000,
- 1058.859375, 0.000000, 1060.921875, 0.000000, 1066.921875, 0.000000, 1072.429688, 0.000000,
- 1075.453125, 0.000000, 1077.515625, 0.000000, 1082.203125, 0.000000, 1088.601562, 0.000000,
- 1092.867188, 0.000000, 1094.976562, 0.000000, 1098.445312, 0.000000, 1102.687500, 0.000000,
- 1106.882812, 0.000000, 1111.570312, 0.000000, 1115.085938, 0.000000, 1117.195312, 0.000000,
- 1117.195312, 0.000000, 1124.015625, 0.000000, 1126.125000, 0.000000, 1132.945312, 0.000000,
- 1135.289062, 0.000000
-
-
-
-
-
-
- أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية
-
-
- 0x00000872, 0x000008D1, 0x000003F9, 0x0000040B, 0x0000088C, 0x0000089E, 0x000008BD, 0x000003EF,
- 0x00000003, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF,
- 0x00000003, 0x000008A8, 0x000008D2, 0x000008C2, 0x0000087D, 0x00000003, 0x000008CE, 0x000008BE,
- 0x000008A9, 0x00000003, 0x0000040D, 0x000008CC, 0x00000876, 0x00000882, 0x000008D1, 0x00000003,
- 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2,
- 0x00000896, 0x00000875, 0x00000003, 0x00000408, 0x0000086C, 0x000008A6, 0x000008C5, 0x00000003,
- 0x00000888, 0x0000087D, 0x000008CC, 0x000008D1, 0x00000003, 0x000008C0, 0x000008BD, 0x0000040B,
- 0x00000003, 0x000003E6, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BE,
- 0x000008BD, 0x00000003, 0x00000408, 0x0000086C, 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5,
- 0x000003EF, 0x00000003, 0x0000040A, 0x0000088A, 0x000008C9, 0x00000003, 0x00000898, 0x000008D2,
- 0x0000089A, 0x00000886, 0x00000875, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2,
- 0x00000896, 0x00000876, 0x000008BE, 0x000008BD, 0x00000003, 0x00000872, 0x000008C2, 0x000008A6,
- 0x000008C5, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000003F2, 0x0000086C, 0x0000086A,
- 0x000008C1, 0x00000003, 0x00000406, 0x0000086C, 0x000008C6, 0x000008C9, 0x00000003, 0x00000409,
- 0x0000086C, 0x000008B9, 0x00000003, 0x000003E6, 0x00000005, 0x000003F7, 0x000008CC, 0x000008BA,
- 0x00000413, 0x000008C5, 0x000008CC, 0x000008D1, 0x00000005, 0x00000003, 0x00000401, 0x000003EF,
- 0x0000088C, 0x00000876, 0x00000885, 0x000003EF, 0x00000003, 0x000008BC, 0x00000870, 0x000008B5,
- 0x0000040B, 0x00000003, 0x00000011, 0x0000086C, 0x000008CA, 0x000008C6, 0x000008C1, 0x00000003,
- 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x000008BC, 0x000008BA, 0x000008BD,
- 0x00000003, 0x0000086C, 0x000008C6, 0x000008D2, 0x000008AA, 0x000008C1, 0x00000003, 0x0000086C,
- 0x000008C2, 0x000008B5, 0x000003F9, 0x00000003, 0x000008D0, 0x000008A2, 0x000008AA, 0x00000412,
- 0x00000875, 0x00000003, 0x00000409, 0x000003EB, 0x00000003, 0x00000888, 0x000008AA, 0x0000086F,
- 0x00000003, 0x0000040C, 0x0000088C, 0x00000885, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003,
- 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, 0x0000040B,
- 0x00000003, 0x00000404, 0x0000088C, 0x00000881, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003,
- 0x000008C4, 0x000008D1, 0x0000088E, 0x00000886, 0x00000876, 0x0000086F, 0x00000003, 0x00000408,
- 0x000008CC, 0x000008B6, 0x00000875, 0x0000040B, 0x00000003, 0x000003E6, 0x00000408, 0x0000086C,
- 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000008A8, 0x000008C1,
- 0x00000003, 0x000008A0, 0x000008B6, 0x000008B1, 0x00000003, 0x0000086E, 0x000008D2, 0x00000891,
- 0x000003EF, 0x000008CC, 0x00000882, 0x000008BD, 0x000003EF, 0x00000003, 0x000008BC, 0x000008C1,
- 0x0000086C, 0x000008AA, 0x00000876, 0x00000875, 0x00000003, 0x000003E6, 0x0000086C, 0x0000040E,
- 0x00000891, 0x0000086C, 0x00000891, 0x000003EB
-
-
-
- 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4,
- 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC,
- 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4,
- 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC,
- 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4,
- 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC,
- 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4,
- 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC,
- 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4,
- 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC,
- 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4,
- 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C,
- 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094,
- 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C,
- 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084,
- 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C,
- 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074,
- 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C,
- 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064,
- 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C,
- 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054,
- 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C,
- 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044,
- 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C,
- 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034,
- 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C,
- 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
- 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C,
- 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014,
- 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C,
- 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004,
- 0x00000003, 0x00000002, 0x00000001, 0x00000000
-
-
-
- 0.000000, 0.000000, 6.316406, 0.000000, 10.382812, 0.000000, 15.492188, 0.000000,
- 21.035156, 0.000000, 27.058594, 0.000000, 39.527344, 0.000000, 43.792969, 0.000000,
- 47.408203, 0.000000, 51.205078, 0.000000, 66.216797, 0.000000, 71.326172, 0.000000,
- 74.695312, 0.000000, 83.367188, 0.000000, 90.826172, 0.000000, 95.091797, 0.000000,
- 98.707031, 0.000000, 102.503906, 0.000000, 109.962891, 0.000000, 114.949219, 0.000000,
- 122.408203, 0.000000, 130.687500, 0.000000, 134.484375, 0.000000, 145.787109, 0.000000,
- 150.773438, 0.000000, 156.884766, 0.000000, 160.681641, 0.000000, 172.277344, 0.000000,
- 177.919922, 0.000000, 182.906250, 0.000000, 191.578125, 0.000000, 195.644531, 0.000000,
- 199.441406, 0.000000, 206.507812, 0.000000, 214.787109, 0.000000, 218.402344, 0.000000,
- 223.945312, 0.000000, 227.742188, 0.000000, 233.765625, 0.000000, 238.751953, 0.000000,
- 245.185547, 0.000000, 257.982422, 0.000000, 262.048828, 0.000000, 265.845703, 0.000000,
- 272.654297, 0.000000, 276.023438, 0.000000, 285.240234, 0.000000, 289.306641, 0.000000,
- 293.103516, 0.000000, 300.169922, 0.000000, 308.449219, 0.000000, 314.091797, 0.000000,
- 318.158203, 0.000000, 321.955078, 0.000000, 329.572266, 0.000000, 333.837891, 0.000000,
- 339.380859, 0.000000, 343.177734, 0.000000, 346.974609, 0.000000, 361.986328, 0.000000,
- 367.095703, 0.000000, 370.464844, 0.000000, 379.136719, 0.000000, 386.595703, 0.000000,
- 391.582031, 0.000000, 395.847656, 0.000000, 399.644531, 0.000000, 406.453125, 0.000000,
- 409.822266, 0.000000, 415.523438, 0.000000, 420.632812, 0.000000, 420.632812, 0.000000,
- 427.441406, 0.000000, 431.056641, 0.000000, 434.853516, 0.000000, 441.357422, 0.000000,
- 448.423828, 0.000000, 455.912109, 0.000000, 459.708984, 0.000000, 479.255859, 0.000000,
- 484.242188, 0.000000, 496.710938, 0.000000, 505.382812, 0.000000, 509.449219, 0.000000,
- 514.992188, 0.000000, 518.789062, 0.000000, 524.812500, 0.000000, 529.798828, 0.000000,
- 536.232422, 0.000000, 549.029297, 0.000000, 554.015625, 0.000000, 559.001953, 0.000000,
- 563.267578, 0.000000, 567.064453, 0.000000, 573.380859, 0.000000, 580.839844, 0.000000,
- 590.056641, 0.000000, 594.123047, 0.000000, 594.123047, 0.000000, 600.931641, 0.000000,
- 604.546875, 0.000000, 608.343750, 0.000000, 620.636719, 0.000000, 624.005859, 0.000000,
- 628.992188, 0.000000, 635.830078, 0.000000, 639.626953, 0.000000, 653.361328, 0.000000,
- 656.730469, 0.000000, 661.716797, 0.000000, 669.205078, 0.000000, 673.001953, 0.000000,
- 683.777344, 0.000000, 687.146484, 0.000000, 692.660156, 0.000000, 696.457031, 0.000000,
- 700.253906, 0.000000, 704.736328, 0.000000, 711.105469, 0.000000, 716.748047, 0.000000,
- 722.994141, 0.000000, 722.994141, 0.000000, 727.060547, 0.000000, 732.703125, 0.000000,
- 736.769531, 0.000000, 741.251953, 0.000000, 745.048828, 0.000000, 752.507812, 0.000000,
- 756.123047, 0.000000, 762.146484, 0.000000, 767.132812, 0.000000, 775.412109, 0.000000,
- 779.027344, 0.000000, 782.824219, 0.000000, 794.203125, 0.000000, 799.189453, 0.000000,
- 804.890625, 0.000000, 810.433594, 0.000000, 814.230469, 0.000000, 818.027344, 0.000000,
- 821.396484, 0.000000, 828.128906, 0.000000, 833.115234, 0.000000, 839.953125, 0.000000,
- 843.750000, 0.000000, 850.816406, 0.000000, 859.095703, 0.000000, 862.710938, 0.000000,
- 868.253906, 0.000000, 872.050781, 0.000000, 883.429688, 0.000000, 889.675781, 0.000000,
- 893.941406, 0.000000, 897.738281, 0.000000, 901.107422, 0.000000, 906.093750, 0.000000,
- 911.080078, 0.000000, 917.800781, 0.000000, 924.638672, 0.000000, 928.435547, 0.000000,
- 931.804688, 0.000000, 939.263672, 0.000000, 944.964844, 0.000000, 950.074219, 0.000000,
- 953.871094, 0.000000, 965.173828, 0.000000, 974.390625, 0.000000, 981.111328, 0.000000,
- 981.111328, 0.000000, 985.177734, 0.000000, 988.974609, 0.000000, 999.750000, 0.000000,
- 1003.365234, 0.000000, 1007.162109, 0.000000, 1014.228516, 0.000000, 1020.949219, 0.000000,
- 1025.015625, 0.000000, 1028.812500, 0.000000, 1040.408203, 0.000000, 1046.431641, 0.000000,
- 1054.710938, 0.000000, 1054.710938, 0.000000, 1061.519531, 0.000000, 1065.134766, 0.000000,
- 1068.931641, 0.000000, 1083.943359, 0.000000, 1089.052734, 0.000000, 1092.421875, 0.000000,
- 1101.093750, 0.000000, 1108.552734, 0.000000, 1112.818359, 0.000000, 1116.433594, 0.000000,
- 1121.976562, 0.000000, 1125.773438, 0.000000, 1140.785156, 0.000000, 1146.808594, 0.000000,
- 1155.087891, 0.000000, 1155.087891, 0.000000, 1161.896484, 0.000000, 1165.511719, 0.000000,
- 1169.308594, 0.000000, 1180.541016, 0.000000, 1184.607422, 0.000000, 1190.630859, 0.000000,
- 1199.302734, 0.000000, 1204.289062, 0.000000, 1208.355469, 0.000000, 1212.152344, 0.000000,
- 1218.960938, 0.000000, 1224.603516, 0.000000, 1231.037109, 0.000000, 1235.103516, 0.000000,
- 1240.646484, 0.000000, 1244.443359, 0.000000, 1248.240234, 0.000000, 1255.048828, 0.000000,
- 1258.417969, 0.000000, 1264.119141, 0.000000, 1269.228516, 0.000000, 1269.228516, 0.000000,
- 1276.037109, 0.000000, 1279.652344, 0.000000, 1283.449219, 0.000000, 1290.908203, 0.000000,
- 1297.746094, 0.000000, 1301.542969, 0.000000, 1311.427734, 0.000000, 1317.861328, 0.000000,
- 1323.562500, 0.000000, 1327.359375, 0.000000, 1341.492188, 0.000000, 1346.478516, 0.000000,
- 1357.904297, 0.000000, 1361.519531, 0.000000, 1367.162109, 0.000000, 1375.833984, 0.000000,
- 1380.099609, 0.000000, 1383.714844, 0.000000, 1387.511719, 0.000000, 1398.890625, 0.000000,
- 1405.728516, 0.000000, 1409.097656, 0.000000, 1415.818359, 0.000000, 1420.804688, 0.000000,
- 1424.871094, 0.000000, 1428.667969, 0.000000, 1432.464844, 0.000000, 1435.833984, 0.000000,
- 1435.833984, 0.000000, 1447.259766, 0.000000, 1450.628906, 0.000000, 1462.054688, 0.000000,
- 1465.669922, 0.000000
-
-
-
-
-
-
- บทที่๑พายุไซโคลนโดโรธีอาศัยอยู่ท่ามกลางทุ่งใหญ่ในแคนซัสกับลุงเฮนรีชาวไร่และป้าเอ็มภรรยาชาวไร่บ้านของพวกเขาหลังเล็กเพราะไม้สร้างบ้านต้องขนมาด้วยเกวียนเป็นระยะทางหลายไมล์
-
-
- 0x000000F3, 0x000000F0, 0x000000F0, 0x0000010E, 0x0000011D, 0x00000126, 0x000000F7, 0x0000010B,
- 0x000000FB, 0x00000111, 0x00000119, 0x000000E4, 0x00000117, 0x000000DD, 0x000000FE, 0x000000F2,
- 0x00000117, 0x000000ED, 0x00000117, 0x000000FC, 0x000000F1, 0x0000010E, 0x00000106, 0x0000010B,
- 0x00000101, 0x0000010A, 0x000000FB, 0x00000106, 0x000000FB, 0x00000112, 0x0000013B, 0x000000F0,
- 0x0000013B, 0x0000010B, 0x000000FA, 0x000000DA, 0x000000FE, 0x0000010B, 0x000000E0, 0x000000F0,
- 0x00000111, 0x0000013B, 0x000000E0, 0x00000118, 0x00000104, 0x000000E6, 0x0000013B, 0x00000118,
- 0x000000F2, 0x00000116, 0x000000DD, 0x000000F2, 0x000000E4, 0x0000010A, 0x00000103, 0x000000DA,
- 0x0000010A, 0x000000F3, 0x000000FE, 0x00000111, 0x000000E0, 0x00000115, 0x00000107, 0x000000F2,
- 0x000000FC, 0x0000010E, 0x000000E3, 0x0000010B, 0x00000100, 0x00000119, 0x000000FC, 0x0000013B,
- 0x00000116, 0x000000FE, 0x00000109, 0x000000F4, 0x00000137, 0x0000010B, 0x00000115, 0x00000106,
- 0x0000011C, 0x000000FA, 0x000000F9, 0x000000FC, 0x000000FC, 0x000000FB, 0x0000010B, 0x000000E3,
- 0x0000010B, 0x00000100, 0x00000119, 0x000000FC, 0x0000013B, 0x000000F3, 0x0000013C, 0x0000010B,
- 0x000000F2, 0x000000DB, 0x00000106, 0x000000E0, 0x000000F7, 0x00000100, 0x000000DA, 0x00000115,
- 0x000000DB, 0x0000010B, 0x00000104, 0x000000FE, 0x0000010A, 0x000000E0, 0x00000115, 0x000000FE,
- 0x0000011C, 0x000000DA, 0x00000115, 0x000000F7, 0x000000FC, 0x0000010B, 0x00000109, 0x00000119,
- 0x000000FA, 0x0000013C, 0x00000103, 0x000000FC, 0x0000013C, 0x0000010B, 0x000000E0, 0x000000F3,
- 0x0000013C, 0x0000010B, 0x000000F2, 0x000000EE, 0x0000013C, 0x00000106, 0x000000E0, 0x000000DB,
- 0x000000F2, 0x000000FA, 0x0000010B, 0x000000ED, 0x0000013C, 0x00000100, 0x000000FB, 0x00000115,
- 0x000000DA, 0x00000100, 0x0000010E, 0x000000FB, 0x000000F2, 0x00000115, 0x000000F4, 0x00000143,
- 0x000000F2, 0x000000FC, 0x00000109, 0x000000FB, 0x00000109, 0x000000F0, 0x0000010B, 0x000000E0,
- 0x00000104, 0x000000FE, 0x0000010B, 0x000000FB, 0x00000119, 0x000000FA, 0x000000FE, 0x0000013F
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F,
- 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027,
- 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F,
- 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037,
- 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F,
- 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047,
- 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F,
- 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057,
- 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F,
- 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067,
- 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F,
- 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077,
- 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F,
- 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087,
- 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F,
- 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097,
- 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F,
- 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7
-
-
-
- 0.000000, 0.000000, 5.399414, 0.000000, 10.798828, 0.000000, 16.198242, 0.000000,
- 16.198242, 0.000000, 16.198242, 0.000000, 21.046875, 0.000000, 26.616211, 0.000000,
- 30.035156, 0.000000, 34.151367, 0.000000, 34.151367, 0.000000, 38.279297, 0.000000,
- 43.558594, 0.000000, 47.663086, 0.000000, 52.438477, 0.000000, 57.178711, 0.000000,
- 62.698242, 0.000000, 66.802734, 0.000000, 71.601562, 0.000000, 75.706055, 0.000000,
- 79.810547, 0.000000, 84.369141, 0.000000, 84.369141, 0.000000, 89.097656, 0.000000,
- 92.516602, 0.000000, 97.195312, 0.000000, 97.195312, 0.000000, 101.311523, 0.000000,
- 106.040039, 0.000000, 110.156250, 0.000000, 110.156250, 0.000000, 110.156250, 0.000000,
- 115.555664, 0.000000, 115.555664, 0.000000, 118.974609, 0.000000, 124.013672, 0.000000,
- 128.765625, 0.000000, 133.505859, 0.000000, 136.924805, 0.000000, 140.704102, 0.000000,
- 146.103516, 0.000000, 146.103516, 0.000000, 146.103516, 0.000000, 149.882812, 0.000000,
- 153.553711, 0.000000, 159.158203, 0.000000, 165.421875, 0.000000, 165.421875, 0.000000,
- 169.092773, 0.000000, 174.612305, 0.000000, 179.135742, 0.000000, 183.911133, 0.000000,
- 189.430664, 0.000000, 194.709961, 0.000000, 194.709961, 0.000000, 199.989258, 0.000000,
- 204.741211, 0.000000, 204.741211, 0.000000, 210.140625, 0.000000, 214.880859, 0.000000,
- 214.880859, 0.000000, 218.660156, 0.000000, 220.675781, 0.000000, 225.128906, 0.000000,
- 230.648438, 0.000000, 234.752930, 0.000000, 234.752930, 0.000000, 239.613281, 0.000000,
- 243.032227, 0.000000, 247.280273, 0.000000, 251.408203, 0.000000, 255.512695, 0.000000,
- 255.512695, 0.000000, 260.036133, 0.000000, 264.776367, 0.000000, 269.071289, 0.000000,
- 274.470703, 0.000000, 274.470703, 0.000000, 277.889648, 0.000000, 279.905273, 0.000000,
- 284.633789, 0.000000, 284.633789, 0.000000, 289.672852, 0.000000, 294.641602, 0.000000,
- 298.746094, 0.000000, 302.850586, 0.000000, 306.966797, 0.000000, 310.385742, 0.000000,
- 315.246094, 0.000000, 318.665039, 0.000000, 322.913086, 0.000000, 327.041016, 0.000000,
- 331.145508, 0.000000, 331.145508, 0.000000, 336.544922, 0.000000, 336.544922, 0.000000,
- 339.963867, 0.000000, 345.483398, 0.000000, 350.258789, 0.000000, 354.987305, 0.000000,
- 358.766602, 0.000000, 364.335938, 0.000000, 368.583984, 0.000000, 373.335938, 0.000000,
- 375.351562, 0.000000, 380.126953, 0.000000, 383.545898, 0.000000, 389.150391, 0.000000,
- 393.890625, 0.000000, 393.890625, 0.000000, 397.669922, 0.000000, 399.685547, 0.000000,
- 404.425781, 0.000000, 404.425781, 0.000000, 409.177734, 0.000000, 411.193359, 0.000000,
- 416.762695, 0.000000, 420.867188, 0.000000, 424.286133, 0.000000, 428.581055, 0.000000,
- 432.708984, 0.000000, 437.748047, 0.000000, 437.748047, 0.000000, 443.027344, 0.000000,
- 447.131836, 0.000000, 447.131836, 0.000000, 450.550781, 0.000000, 454.330078, 0.000000,
- 459.729492, 0.000000, 459.729492, 0.000000, 463.148438, 0.000000, 468.667969, 0.000000,
- 473.478516, 0.000000, 473.478516, 0.000000, 478.207031, 0.000000, 481.986328, 0.000000,
- 486.761719, 0.000000, 492.281250, 0.000000, 497.320312, 0.000000, 500.739258, 0.000000,
- 505.538086, 0.000000, 505.538086, 0.000000, 509.786133, 0.000000, 513.902344, 0.000000,
- 515.917969, 0.000000, 520.669922, 0.000000, 524.917969, 0.000000, 524.917969, 0.000000,
- 529.034180, 0.000000, 534.553711, 0.000000, 536.569336, 0.000000, 541.968750, 0.000000,
- 541.968750, 0.000000, 547.488281, 0.000000, 551.592773, 0.000000, 555.887695, 0.000000,
- 560.003906, 0.000000, 564.298828, 0.000000, 569.698242, 0.000000, 573.117188, 0.000000,
- 576.896484, 0.000000, 582.500977, 0.000000, 587.241211, 0.000000, 590.660156, 0.000000,
- 594.776367, 0.000000, 598.904297, 0.000000, 603.943359, 0.000000, 608.683594, 0.000000,
- 608.683594, 0.000000
-
-
-
-
-
-
- أساسًا، تتعامل الحواسيب فقط مع الأرقام، وتقوم بتخزين الأحرف والمحارف الأخرى بعد أن تُعطي رقما معينا لكل واحد منها. وقبل اختراع "يونِكود"، كان هناك مئات الأنظمة للتشفير وتخصيص هذه الأرقام للمحارف، ولم يوجد نظام تشفير واحد يحتوي على جميع المحارف الضرورية
-
-
- 0x00000872, 0x000008D1, 0x000003F9, 0x0000040B, 0x0000088C, 0x0000089E, 0x000008BD, 0x000003EF,
- 0x00000003, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF,
- 0x00000003, 0x000008A8, 0x000008D2, 0x000008C2, 0x0000087D, 0x00000003, 0x000008CE, 0x000008BE,
- 0x000008A9, 0x00000003, 0x0000040D, 0x000008CC, 0x00000876, 0x00000882, 0x000008D1, 0x00000003,
- 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2,
- 0x00000896, 0x00000875, 0x00000003, 0x00000408, 0x0000086C, 0x000008A6, 0x000008C5, 0x00000003,
- 0x00000888, 0x0000087D, 0x000008CC, 0x000008D1, 0x00000003, 0x000008C0, 0x000008BD, 0x0000040B,
- 0x00000003, 0x000003E6, 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BE,
- 0x000008BD, 0x00000003, 0x00000408, 0x0000086C, 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5,
- 0x000003EF, 0x00000003, 0x0000040A, 0x0000088A, 0x000008C9, 0x00000003, 0x00000898, 0x000008D2,
- 0x0000089A, 0x00000886, 0x00000875, 0x0000040B, 0x00000003, 0x0000088C, 0x000008D2, 0x000008B2,
- 0x00000896, 0x00000876, 0x000008BE, 0x000008BD, 0x00000003, 0x00000872, 0x000008C2, 0x000008A6,
- 0x000008C5, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000003F2, 0x0000086C, 0x0000086A,
- 0x000008C1, 0x00000003, 0x00000406, 0x0000086C, 0x000008C6, 0x000008C9, 0x00000003, 0x00000409,
- 0x0000086C, 0x000008B9, 0x00000003, 0x000003E6, 0x00000005, 0x000003F7, 0x000008CC, 0x000008BA,
- 0x00000413, 0x000008C5, 0x000008CC, 0x000008D1, 0x00000005, 0x00000003, 0x00000401, 0x000003EF,
- 0x0000088C, 0x00000876, 0x00000885, 0x000003EF, 0x00000003, 0x000008BC, 0x00000870, 0x000008B5,
- 0x0000040B, 0x00000003, 0x00000011, 0x0000086C, 0x000008CA, 0x000008C6, 0x000008C1, 0x00000003,
- 0x00000888, 0x00000881, 0x000003EF, 0x0000040B, 0x00000003, 0x000008BC, 0x000008BA, 0x000008BD,
- 0x00000003, 0x0000086C, 0x000008C6, 0x000008D2, 0x000008AA, 0x000008C1, 0x00000003, 0x0000086C,
- 0x000008C2, 0x000008B5, 0x000003F9, 0x00000003, 0x000008D0, 0x000008A2, 0x000008AA, 0x00000412,
- 0x00000875, 0x00000003, 0x00000409, 0x000003EB, 0x00000003, 0x00000888, 0x000008AA, 0x0000086F,
- 0x00000003, 0x0000040C, 0x0000088C, 0x00000885, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003,
- 0x00000404, 0x000003F9, 0x0000086C, 0x00000882, 0x000008C2, 0x000008BD, 0x000003EF, 0x0000040B,
- 0x00000003, 0x00000404, 0x0000088C, 0x00000881, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003,
- 0x000008C4, 0x000008D1, 0x0000088E, 0x00000886, 0x00000876, 0x0000086F, 0x00000003, 0x00000408,
- 0x000008CC, 0x000008B6, 0x00000875, 0x0000040B, 0x00000003, 0x000003E6, 0x00000408, 0x0000086C,
- 0x000008B5, 0x000003F9, 0x0000FFFF, 0x000008D5, 0x000003EF, 0x00000003, 0x000008A8, 0x000008C1,
- 0x00000003, 0x000008A0, 0x000008B6, 0x000008B1, 0x00000003, 0x0000086E, 0x000008D2, 0x00000891,
- 0x000003EF, 0x000008CC, 0x00000882, 0x000008BD, 0x000003EF, 0x00000003, 0x000008BC, 0x000008C1,
- 0x0000086C, 0x000008AA, 0x00000876, 0x00000875, 0x00000003, 0x000003E6, 0x0000086C, 0x0000040E,
- 0x00000891, 0x0000086C, 0x00000891, 0x000003EB
-
-
-
- 0x000000FB, 0x000000FA, 0x000000F9, 0x000000F8, 0x000000F7, 0x000000F6, 0x000000F5, 0x000000F4,
- 0x000000F3, 0x000000F2, 0x000000F1, 0x000000F0, 0x000000EF, 0x000000EE, 0x000000ED, 0x000000EC,
- 0x000000EB, 0x000000EA, 0x000000E9, 0x000000E8, 0x000000E7, 0x000000E6, 0x000000E5, 0x000000E4,
- 0x000000E3, 0x000000E2, 0x000000E1, 0x000000E0, 0x000000DF, 0x000000DE, 0x000000DD, 0x000000DC,
- 0x000000DB, 0x000000DA, 0x000000D9, 0x000000D8, 0x000000D7, 0x000000D6, 0x000000D5, 0x000000D4,
- 0x000000D3, 0x000000D2, 0x000000D1, 0x000000D0, 0x000000CF, 0x000000CE, 0x000000CD, 0x000000CC,
- 0x000000CB, 0x000000CA, 0x000000C9, 0x000000C8, 0x000000C7, 0x000000C6, 0x000000C5, 0x000000C4,
- 0x000000C3, 0x000000C2, 0x000000C1, 0x000000C0, 0x000000BF, 0x000000BE, 0x000000BD, 0x000000BC,
- 0x000000BB, 0x000000BA, 0x000000B9, 0x000000B8, 0x000000B7, 0x000000B6, 0x000000B5, 0x000000B4,
- 0x000000B3, 0x000000B2, 0x000000B1, 0x000000B0, 0x000000AF, 0x000000AE, 0x000000AD, 0x000000AC,
- 0x000000AB, 0x000000AA, 0x000000A9, 0x000000A8, 0x000000A7, 0x000000A6, 0x000000A5, 0x000000A4,
- 0x000000A3, 0x000000A2, 0x000000A1, 0x000000A0, 0x0000009F, 0x0000009E, 0x0000009D, 0x0000009C,
- 0x0000009B, 0x0000009A, 0x00000099, 0x00000098, 0x00000097, 0x00000096, 0x00000095, 0x00000094,
- 0x00000093, 0x00000092, 0x00000091, 0x00000090, 0x0000008F, 0x0000008E, 0x0000008D, 0x0000008C,
- 0x0000008B, 0x0000008A, 0x00000089, 0x00000088, 0x00000087, 0x00000086, 0x00000085, 0x00000084,
- 0x00000083, 0x00000082, 0x00000081, 0x00000080, 0x0000007F, 0x0000007E, 0x0000007D, 0x0000007C,
- 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075, 0x00000074,
- 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D, 0x0000006C,
- 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065, 0x00000064,
- 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D, 0x0000005C,
- 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055, 0x00000054,
- 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D, 0x0000004C,
- 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, 0x00000044,
- 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D, 0x0000003C,
- 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034,
- 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D, 0x0000002C,
- 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
- 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D, 0x0000001C,
- 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, 0x00000014,
- 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D, 0x0000000C,
- 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004,
- 0x00000003, 0x00000002, 0x00000001, 0x00000000
-
-
-
- 0.000000, 0.000000, 6.316406, 0.000000, 10.382812, 0.000000, 15.492188, 0.000000,
- 21.035156, 0.000000, 27.058594, 0.000000, 39.527344, 0.000000, 43.792969, 0.000000,
- 47.408203, 0.000000, 51.205078, 0.000000, 66.216797, 0.000000, 71.326172, 0.000000,
- 74.695312, 0.000000, 83.367188, 0.000000, 90.826172, 0.000000, 95.091797, 0.000000,
- 98.707031, 0.000000, 102.503906, 0.000000, 109.962891, 0.000000, 114.949219, 0.000000,
- 122.408203, 0.000000, 130.687500, 0.000000, 134.484375, 0.000000, 145.787109, 0.000000,
- 150.773438, 0.000000, 156.884766, 0.000000, 160.681641, 0.000000, 172.277344, 0.000000,
- 177.919922, 0.000000, 182.906250, 0.000000, 191.578125, 0.000000, 195.644531, 0.000000,
- 199.441406, 0.000000, 206.507812, 0.000000, 214.787109, 0.000000, 218.402344, 0.000000,
- 223.945312, 0.000000, 227.742188, 0.000000, 233.765625, 0.000000, 238.751953, 0.000000,
- 245.185547, 0.000000, 257.982422, 0.000000, 262.048828, 0.000000, 265.845703, 0.000000,
- 272.654297, 0.000000, 276.023438, 0.000000, 285.240234, 0.000000, 289.306641, 0.000000,
- 293.103516, 0.000000, 300.169922, 0.000000, 308.449219, 0.000000, 314.091797, 0.000000,
- 318.158203, 0.000000, 321.955078, 0.000000, 329.572266, 0.000000, 333.837891, 0.000000,
- 339.380859, 0.000000, 343.177734, 0.000000, 346.974609, 0.000000, 361.986328, 0.000000,
- 367.095703, 0.000000, 370.464844, 0.000000, 379.136719, 0.000000, 386.595703, 0.000000,
- 391.582031, 0.000000, 395.847656, 0.000000, 399.644531, 0.000000, 406.453125, 0.000000,
- 409.822266, 0.000000, 415.523438, 0.000000, 420.632812, 0.000000, 420.632812, 0.000000,
- 427.441406, 0.000000, 431.056641, 0.000000, 434.853516, 0.000000, 441.357422, 0.000000,
- 448.423828, 0.000000, 455.912109, 0.000000, 459.708984, 0.000000, 479.255859, 0.000000,
- 484.242188, 0.000000, 496.710938, 0.000000, 505.382812, 0.000000, 509.449219, 0.000000,
- 514.992188, 0.000000, 518.789062, 0.000000, 524.812500, 0.000000, 529.798828, 0.000000,
- 536.232422, 0.000000, 549.029297, 0.000000, 554.015625, 0.000000, 559.001953, 0.000000,
- 563.267578, 0.000000, 567.064453, 0.000000, 573.380859, 0.000000, 580.839844, 0.000000,
- 590.056641, 0.000000, 594.123047, 0.000000, 594.123047, 0.000000, 600.931641, 0.000000,
- 604.546875, 0.000000, 608.343750, 0.000000, 620.636719, 0.000000, 624.005859, 0.000000,
- 628.992188, 0.000000, 635.830078, 0.000000, 639.626953, 0.000000, 653.361328, 0.000000,
- 656.730469, 0.000000, 661.716797, 0.000000, 669.205078, 0.000000, 673.001953, 0.000000,
- 683.777344, 0.000000, 687.146484, 0.000000, 692.660156, 0.000000, 696.457031, 0.000000,
- 700.253906, 0.000000, 704.736328, 0.000000, 711.105469, 0.000000, 716.748047, 0.000000,
- 722.994141, 0.000000, 722.994141, 0.000000, 727.060547, 0.000000, 732.703125, 0.000000,
- 736.769531, 0.000000, 741.251953, 0.000000, 745.048828, 0.000000, 752.507812, 0.000000,
- 756.123047, 0.000000, 762.146484, 0.000000, 767.132812, 0.000000, 775.412109, 0.000000,
- 779.027344, 0.000000, 782.824219, 0.000000, 794.203125, 0.000000, 799.189453, 0.000000,
- 804.890625, 0.000000, 810.433594, 0.000000, 814.230469, 0.000000, 818.027344, 0.000000,
- 821.396484, 0.000000, 828.128906, 0.000000, 833.115234, 0.000000, 839.953125, 0.000000,
- 843.750000, 0.000000, 850.816406, 0.000000, 859.095703, 0.000000, 862.710938, 0.000000,
- 868.253906, 0.000000, 872.050781, 0.000000, 883.429688, 0.000000, 889.675781, 0.000000,
- 893.941406, 0.000000, 897.738281, 0.000000, 901.107422, 0.000000, 906.093750, 0.000000,
- 911.080078, 0.000000, 917.800781, 0.000000, 924.638672, 0.000000, 928.435547, 0.000000,
- 931.804688, 0.000000, 939.263672, 0.000000, 944.964844, 0.000000, 950.074219, 0.000000,
- 953.871094, 0.000000, 965.173828, 0.000000, 974.390625, 0.000000, 981.111328, 0.000000,
- 981.111328, 0.000000, 985.177734, 0.000000, 988.974609, 0.000000, 999.750000, 0.000000,
- 1003.365234, 0.000000, 1007.162109, 0.000000, 1014.228516, 0.000000, 1020.949219, 0.000000,
- 1025.015625, 0.000000, 1028.812500, 0.000000, 1040.408203, 0.000000, 1046.431641, 0.000000,
- 1054.710938, 0.000000, 1054.710938, 0.000000, 1061.519531, 0.000000, 1065.134766, 0.000000,
- 1068.931641, 0.000000, 1083.943359, 0.000000, 1089.052734, 0.000000, 1092.421875, 0.000000,
- 1101.093750, 0.000000, 1108.552734, 0.000000, 1112.818359, 0.000000, 1116.433594, 0.000000,
- 1121.976562, 0.000000, 1125.773438, 0.000000, 1140.785156, 0.000000, 1146.808594, 0.000000,
- 1155.087891, 0.000000, 1155.087891, 0.000000, 1161.896484, 0.000000, 1165.511719, 0.000000,
- 1169.308594, 0.000000, 1180.541016, 0.000000, 1184.607422, 0.000000, 1190.630859, 0.000000,
- 1199.302734, 0.000000, 1204.289062, 0.000000, 1208.355469, 0.000000, 1212.152344, 0.000000,
- 1218.960938, 0.000000, 1224.603516, 0.000000, 1231.037109, 0.000000, 1235.103516, 0.000000,
- 1240.646484, 0.000000, 1244.443359, 0.000000, 1248.240234, 0.000000, 1255.048828, 0.000000,
- 1258.417969, 0.000000, 1264.119141, 0.000000, 1269.228516, 0.000000, 1269.228516, 0.000000,
- 1276.037109, 0.000000, 1279.652344, 0.000000, 1283.449219, 0.000000, 1290.908203, 0.000000,
- 1297.746094, 0.000000, 1301.542969, 0.000000, 1311.427734, 0.000000, 1317.861328, 0.000000,
- 1323.562500, 0.000000, 1327.359375, 0.000000, 1341.492188, 0.000000, 1346.478516, 0.000000,
- 1357.904297, 0.000000, 1361.519531, 0.000000, 1367.162109, 0.000000, 1375.833984, 0.000000,
- 1380.099609, 0.000000, 1383.714844, 0.000000, 1387.511719, 0.000000, 1398.890625, 0.000000,
- 1405.728516, 0.000000, 1409.097656, 0.000000, 1415.818359, 0.000000, 1420.804688, 0.000000,
- 1424.871094, 0.000000, 1428.667969, 0.000000, 1432.464844, 0.000000, 1435.833984, 0.000000,
- 1435.833984, 0.000000, 1447.259766, 0.000000, 1450.628906, 0.000000, 1462.054688, 0.000000,
- 1465.669922, 0.000000
-
-
-
-
-
-
- ुं ं॑
-
-
- 0x0000029C, 0x000001D5, 0x00000232, 0x00000003, 0x0000029C, 0x00000232, 0x00000233
-
-
-
- 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000003, 0x00000004
-
-
-
- 0.000000, 0.000000, 7.541016, 0.000000, 7.541016, 0.000000, 7.541016, 0.000000,
- 13.541016, 0.000000, 21.082031, 0.000000, 19.953125, -6.052734, 21.082031, 0.000000
-
-
-
-
-
-
- कँ कं कः क॑ क॒ कँ॑ कं॒ कँंः क॒॑
-
-
- 0x00000080, 0x00000231, 0x00000003, 0x00000080, 0x00000232, 0x00000003, 0x00000080, 0x0000022C,
- 0x00000003, 0x00000080, 0x00000233, 0x00000003, 0x00000080, 0x000001DF, 0x00000003, 0x00000080,
- 0x00000231, 0x00000233, 0x00000003, 0x00000080, 0x000001DF, 0x00000232, 0x00000003, 0x00000080,
- 0x00000231, 0x0000029C, 0x00000232, 0x0000029C, 0x0000022C, 0x00000003, 0x00000080, 0x00000233,
- 0x0000029C, 0x000001DF
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000015, 0x00000014, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019, 0x00000019, 0x0000001A, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D,
- 0x0000001E, 0x0000001E
-
-
-
- 0.000000, 0.000000, 10.001953, -0.087891, 10.875000, 0.000000, 16.875000, 0.000000,
- 23.783203, 0.439453, 27.750000, 0.000000, 33.750000, 0.000000, 44.625000, 0.000000,
- 48.984375, 0.000000, 54.984375, 0.000000, 63.546875, -1.669922, 65.859375, 0.000000,
- 71.859375, 0.000000, 80.332031, 0.492188, 82.734375, 0.000000, 88.734375, 0.000000,
- 98.736328, -0.087891, 97.431641, -6.228516, 99.609375, 0.000000, 105.609375, 0.000000,
- 114.082031, 0.492188, 112.517578, 0.439453, 116.484375, 0.000000, 122.484375, 0.000000,
- 132.486328, -0.087891, 133.359375, 0.000000, 140.900391, 0.000000, 140.900391, 0.000000,
- 148.441406, 0.000000, 152.800781, 0.000000, 158.800781, 0.000000, 167.363281, -1.669922,
- 169.675781, 0.000000, 177.216797, 0.000000, 177.216797, 0.000000
-
-
-
-
-
-
- रू क़् क्ष क्कि क्रि ट्रि हिन्दी र्क्रिं क्षत्रज्ञत्रक्ष श्र थ्र श्र कके र्कें केूकूेकेृ र्कू क़ क क् क्ष क्ष् क्ष्क ज़ ज ज् ज्ञ ज्ञ् ज्ञ्क र्क र्क्क ड्र क्क क़्क क़्क क़् क्ष्क क्ष् त्र्क द्द कि हि रू रु र्के र्कं क् कु के द्द्द क़्ष क्ष र्क्षे द्दत्र्क ज्ञ क्त्व ज्ञ्क र्कँ र्किँ र्केँ र्क्रिँ हिंदी ह्मिह्यिखि ङ्क ङ्म ङ्क्त ङ्ख ङ्ग ङ्घ ङ्क्ष ङ्क्ष्व ङ्क्ष्य र्क्त्वि र्र्र्र कै के कु कू कृ कॅ कॆ हु हू हॆ है हे
-
-
- 0x0000009A, 0x000001FE, 0x00000003, 0x000000A4, 0x00000051, 0x00000003, 0x000000A2, 0x0000FFFF,
- 0x0000FFFF, 0x00000003, 0x000001D4, 0x000000C8, 0x0000FFFF, 0x00000080, 0x00000003, 0x000001D1,
- 0x00000080, 0x0000009A, 0x00000051, 0x00000003, 0x000001D1, 0x0000008A, 0x0000009A, 0x00000051,
- 0x00000003, 0x000001D1, 0x000000A1, 0x000000DB, 0x0000FFFF, 0x00000091, 0x00000223, 0x00000003,
- 0x000001D1, 0x00000080, 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000232, 0x00000003,
- 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x0000008F, 0x000000E2, 0x0000FFFF, 0x000000A3, 0x0000FFFF,
- 0x0000FFFF, 0x0000008F, 0x000000E2, 0x0000FFFF, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003,
- 0x0000009E, 0x0000009A, 0x00000051, 0x00000003, 0x00000090, 0x0000009A, 0x00000051, 0x00000003,
- 0x0000009E, 0x0000009A, 0x00000051, 0x00000003, 0x00000080, 0x00000080, 0x0000022F, 0x00000003,
- 0x00000080, 0x0000022F, 0x0000024D, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x0000022F,
- 0x0000029C, 0x000001D7, 0x00000080, 0x000001D7, 0x0000029C, 0x0000022F, 0x00000080, 0x0000022F,
- 0x0000029C, 0x000001D9, 0x00000003, 0x00000080, 0x000001D7, 0x0000005B, 0x0000FFFF, 0x00000003,
- 0x000000A4, 0x00000003, 0x00000080, 0x00000003, 0x00000080, 0x00000051, 0x00000003, 0x000000A2,
- 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003,
- 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000003, 0x000000AB,
- 0x0000FFFF, 0x00000003, 0x00000087, 0x00000003, 0x00000087, 0x00000051, 0x00000003, 0x000000A3,
- 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A3, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003,
- 0x000000EB, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000080, 0x0000005B,
- 0x0000FFFF, 0x00000003, 0x000000C8, 0x0000FFFF, 0x00000080, 0x0000005B, 0x0000FFFF, 0x00000003,
- 0x0000008C, 0x0000009A, 0x00000051, 0x00000003, 0x000000C8, 0x0000FFFF, 0x00000080, 0x00000003,
- 0x000000EC, 0x0000FFFF, 0x00000080, 0x00000003, 0x000000EC, 0x0000FFFF, 0x00000080, 0x00000003,
- 0x000000A4, 0x00000051, 0x00000003, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080,
- 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000051, 0x00000003, 0x000000D7, 0x0000FFFF,
- 0x000000E2, 0x0000FFFF, 0x00000080, 0x00000003, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x00000003,
- 0x000001D1, 0x00000080, 0x00000003, 0x000001D1, 0x000000A1, 0x00000003, 0x0000009A, 0x000001FE,
- 0x00000003, 0x0000009A, 0x000001FD, 0x00000003, 0x00000080, 0x0000022F, 0x0000005A, 0x0000FFFF,
- 0x00000003, 0x00000080, 0x0000024D, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x00000051,
- 0x00000003, 0x00000080, 0x000001D5, 0x00000003, 0x00000080, 0x0000022F, 0x00000003, 0x000000D9,
- 0x0000FFFF, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000EC, 0x0000FFFF, 0x0000009F,
- 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000A2, 0x0000FFFF, 0x0000FFFF,
- 0x0000022F, 0x0000005A, 0x0000FFFF, 0x00000003, 0x000001A7, 0x0000FFFF, 0x0000FFFF, 0x000000D7,
- 0x0000FFFF, 0x000000E2, 0x0000FFFF, 0x00000080, 0x00000003, 0x000000A3, 0x0000FFFF, 0x0000FFFF,
- 0x00000003, 0x000000C8, 0x0000FFFF, 0x000000D7, 0x0000FFFF, 0x0000009D, 0x00000003, 0x000000EB,
- 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000080, 0x00000003, 0x00000080, 0x0000024C, 0x0000FFFF,
- 0x0000FFFF, 0x00000003, 0x000001D1, 0x00000080, 0x0000024C, 0x0000FFFF, 0x0000FFFF, 0x00000003,
- 0x00000080, 0x0000022F, 0x0000024C, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000001D1, 0x00000080,
- 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000231, 0x00000003, 0x000001D1, 0x000000A1,
- 0x00000232, 0x00000091, 0x00000223, 0x00000003, 0x000001D3, 0x000001BA, 0x0000FFFF, 0x0000FFFF,
- 0x000001D3, 0x000001BB, 0x0000FFFF, 0x0000FFFF, 0x000001D4, 0x00000081, 0x00000003, 0x000000CC,
- 0x0000FFFF, 0x00000080, 0x00000003, 0x000001A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC,
- 0x0000FFFF, 0x000001A0, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000081,
- 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000082, 0x00000003, 0x000000CC, 0x0000FFFF, 0x00000083,
- 0x00000003, 0x000000CC, 0x0000FFFF, 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x000000CC,
- 0x0000FFFF, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000009D, 0x00000003, 0x000000CC,
- 0x0000FFFF, 0x000000EA, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000099, 0x00000003, 0x000001D4,
- 0x000000C8, 0x0000FFFF, 0x000000D7, 0x0000FFFF, 0x0000009D, 0x0000005B, 0x0000FFFF, 0x00000003,
- 0x0000009A, 0x00000051, 0x0000009A, 0x000000E2, 0x0000FFFF, 0x0000009A, 0x00000051, 0x00000003,
- 0x00000080, 0x00000230, 0x00000003, 0x00000080, 0x0000022F, 0x00000003, 0x00000080, 0x000001D5,
- 0x00000003, 0x00000080, 0x000001D7, 0x00000003, 0x00000080, 0x000001D9, 0x00000003, 0x00000080,
- 0x0000022D, 0x00000003, 0x00000080, 0x0000022E, 0x00000003, 0x000000A1, 0x000001D5, 0x00000003,
- 0x000000A1, 0x000001D7, 0x00000003, 0x000000A1, 0x0000022E, 0x00000003, 0x000000A1, 0x00000230,
- 0x00000003, 0x000000A1, 0x0000022F
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000D, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000E, 0x00000012,
- 0x0000000F, 0x00000011, 0x00000010, 0x00000013, 0x00000017, 0x00000014, 0x00000016, 0x00000015,
- 0x00000018, 0x0000001A, 0x00000019, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F,
- 0x00000025, 0x00000022, 0x00000024, 0x00000023, 0x00000020, 0x00000021, 0x00000026, 0x00000027,
- 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002D, 0x0000002C, 0x0000002E, 0x0000002F,
- 0x00000030, 0x00000031, 0x00000033, 0x00000032, 0x00000034, 0x00000035, 0x00000036, 0x00000037,
- 0x00000038, 0x0000003A, 0x00000039, 0x0000003B, 0x0000003C, 0x0000003E, 0x0000003D, 0x0000003F,
- 0x00000040, 0x00000042, 0x00000041, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047,
- 0x0000004A, 0x0000004B, 0x00000048, 0x00000049, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F,
- 0x00000050, 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000053, 0x00000054, 0x00000055,
- 0x00000056, 0x00000056, 0x00000057, 0x0000005A, 0x0000005B, 0x00000058, 0x00000059, 0x0000005C,
- 0x0000005D, 0x0000005E, 0x0000005F, 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064,
- 0x00000065, 0x00000066, 0x00000067, 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C,
- 0x0000006D, 0x0000006E, 0x0000006F, 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074,
- 0x00000075, 0x00000076, 0x00000077, 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C,
- 0x0000007D, 0x0000007E, 0x0000007F, 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084,
- 0x00000085, 0x00000086, 0x00000087, 0x00000088, 0x00000089, 0x0000008A, 0x0000008D, 0x0000008B,
- 0x0000008C, 0x0000008E, 0x00000091, 0x00000092, 0x00000093, 0x0000008F, 0x00000090, 0x00000094,
- 0x00000095, 0x00000097, 0x00000096, 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C,
- 0x0000009D, 0x0000009E, 0x0000009F, 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4,
- 0x000000A5, 0x000000A6, 0x000000A7, 0x000000A8, 0x000000A9, 0x000000AA, 0x000000AB, 0x000000AC,
- 0x000000AD, 0x000000AE, 0x000000AF, 0x000000B0, 0x000000B1, 0x000000B2, 0x000000B3, 0x000000B4,
- 0x000000B5, 0x000000B6, 0x000000B7, 0x000000B8, 0x000000B9, 0x000000BA, 0x000000BB, 0x000000BC,
- 0x000000BE, 0x000000BD, 0x000000BF, 0x000000C1, 0x000000C0, 0x000000C2, 0x000000C3, 0x000000C4,
- 0x000000C5, 0x000000C6, 0x000000C7, 0x000000C8, 0x000000CB, 0x000000CC, 0x000000C9, 0x000000CA,
- 0x000000CD, 0x000000D0, 0x000000CE, 0x000000CF, 0x000000D1, 0x000000D2, 0x000000D3, 0x000000D4,
- 0x000000D5, 0x000000D6, 0x000000D7, 0x000000D8, 0x000000D9, 0x000000DA, 0x000000DB, 0x000000DC,
- 0x000000DD, 0x000000DE, 0x000000DF, 0x000000E0, 0x000000E1, 0x000000E2, 0x000000E3, 0x000000E4,
- 0x000000E5, 0x000000E6, 0x000000E7, 0x000000E8, 0x000000E9, 0x000000EC, 0x000000ED, 0x000000EE,
- 0x000000EF, 0x000000EA, 0x000000EB, 0x000000F0, 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4,
- 0x000000F5, 0x000000F6, 0x000000F7, 0x000000F8, 0x000000F9, 0x000000FA, 0x000000FB, 0x000000FC,
- 0x000000FD, 0x000000FE, 0x000000FF, 0x00000100, 0x00000101, 0x00000102, 0x00000103, 0x00000104,
- 0x00000105, 0x00000106, 0x00000107, 0x00000108, 0x00000109, 0x0000010C, 0x0000010A, 0x0000010B,
- 0x0000010D, 0x0000010E, 0x00000112, 0x00000111, 0x0000010F, 0x00000110, 0x00000113, 0x00000114,
- 0x00000117, 0x00000118, 0x00000115, 0x00000116, 0x00000119, 0x0000011A, 0x00000120, 0x0000011D,
- 0x0000011F, 0x0000011E, 0x0000011B, 0x0000011C, 0x00000121, 0x00000122, 0x00000124, 0x00000123,
- 0x00000125, 0x00000126, 0x00000127, 0x00000128, 0x0000012C, 0x00000129, 0x0000012A, 0x0000012B,
- 0x00000130, 0x0000012D, 0x0000012E, 0x0000012F, 0x00000132, 0x00000131, 0x00000133, 0x00000134,
- 0x00000135, 0x00000136, 0x00000137, 0x00000138, 0x00000139, 0x0000013A, 0x0000013B, 0x0000013C,
- 0x0000013D, 0x0000013E, 0x0000013F, 0x00000140, 0x00000141, 0x00000142, 0x00000143, 0x00000144,
- 0x00000145, 0x00000146, 0x00000147, 0x00000148, 0x00000149, 0x0000014A, 0x0000014B, 0x0000014C,
- 0x0000014D, 0x0000014E, 0x0000014F, 0x00000150, 0x00000151, 0x00000152, 0x00000153, 0x00000154,
- 0x00000155, 0x00000156, 0x00000157, 0x00000158, 0x00000159, 0x0000015A, 0x0000015B, 0x0000015C,
- 0x0000015D, 0x0000015E, 0x0000015F, 0x00000160, 0x00000161, 0x00000162, 0x00000163, 0x0000016B,
- 0x00000166, 0x00000167, 0x00000168, 0x00000169, 0x0000016A, 0x00000164, 0x00000165, 0x0000016C,
- 0x0000016F, 0x00000170, 0x00000171, 0x00000173, 0x00000172, 0x0000016D, 0x0000016E, 0x00000174,
- 0x00000175, 0x00000176, 0x00000177, 0x00000178, 0x00000179, 0x0000017A, 0x0000017B, 0x0000017C,
- 0x0000017D, 0x0000017E, 0x0000017F, 0x00000180, 0x00000181, 0x00000182, 0x00000183, 0x00000184,
- 0x00000185, 0x00000186, 0x00000187, 0x00000188, 0x00000189, 0x0000018A, 0x0000018B, 0x0000018C,
- 0x0000018D, 0x0000018E, 0x0000018F, 0x00000190, 0x00000191, 0x00000192, 0x00000193, 0x00000194,
- 0x00000195, 0x00000196, 0x00000197
-
-
-
- 0.000000, 0.000000, 6.515625, 0.000000, 8.121094, 0.000000, 14.121094, 0.000000,
- 24.861328, -0.451172, 24.996094, 0.000000, 30.996094, 0.000000, 41.871094, 0.000000,
- 41.871094, 0.000000, 41.871094, 0.000000, 47.871094, 0.000000, 52.230469, 0.000000,
- 60.949219, 0.000000, 60.949219, 0.000000, 71.824219, 0.000000, 77.824219, 0.000000,
- 82.183594, 0.000000, 93.058594, 0.000000, 102.720703, -0.451172, 99.574219, 0.000000,
- 105.574219, 0.000000, 109.933594, 0.000000, 117.902344, 0.000000, 127.564453, -0.451172,
- 124.417969, 0.000000, 130.417969, 0.000000, 134.777344, 0.000000, 142.746094, 0.000000,
- 150.011719, 0.000000, 150.011719, 0.000000, 157.980469, 0.000000, 161.636719, 0.000000,
- 167.636719, 0.000000, 171.996094, 0.000000, 182.871094, 0.000000, 186.621094, 0.000000,
- 186.621094, 0.000000, 196.283203, -0.451172, 191.613281, 0.439453, 193.136719, 0.000000,
- 199.136719, 0.000000, 210.011719, 0.000000, 210.011719, 0.000000, 210.011719, 0.000000,
- 217.980469, 0.000000, 221.730469, 0.000000, 221.730469, 0.000000, 232.605469, 0.000000,
- 232.605469, 0.000000, 232.605469, 0.000000, 240.574219, 0.000000, 244.324219, 0.000000,
- 244.324219, 0.000000, 255.199219, 0.000000, 255.199219, 0.000000, 255.199219, 0.000000,
- 261.199219, 0.000000, 270.667969, 0.000000, 280.330078, -0.451172, 277.183594, 0.000000,
- 283.183594, 0.000000, 292.652344, 0.000000, 302.314453, -0.451172, 299.167969, 0.000000,
- 305.167969, 0.000000, 314.636719, 0.000000, 324.298828, -0.451172, 321.152344, 0.000000,
- 327.152344, 0.000000, 338.027344, 0.000000, 344.783203, 0.263672, 348.902344, 0.000000,
- 354.902344, 0.000000, 361.658203, 0.263672, 362.279297, 0.263672, 365.777344, 0.000000,
- 365.777344, 0.000000, 365.777344, 0.000000, 371.777344, 0.000000, 378.533203, 0.263672,
- 382.652344, 0.000000, 390.193359, 0.000000, 390.193359, 0.000000, 397.916016, -0.011719,
- 401.068359, 0.000000, 408.609375, 0.000000, 408.609375, 0.000000, 415.365234, 0.263672,
- 419.484375, 0.000000, 427.025391, 0.000000, 427.025391, 0.000000, 433.025391, 0.000000,
- 440.748047, -0.011719, 440.929688, 0.263672, 443.900391, 0.000000, 443.900391, 0.000000,
- 449.900391, 0.000000, 460.775391, 0.000000, 466.775391, 0.000000, 477.650391, 0.000000,
- 483.650391, 0.000000, 494.390625, -0.451172, 494.525391, 0.000000, 500.525391, 0.000000,
- 511.400391, 0.000000, 511.400391, 0.000000, 511.400391, 0.000000, 517.400391, 0.000000,
- 528.275391, 0.000000, 528.275391, 0.000000, 531.457031, -0.451172, 528.275391, 0.000000,
- 534.275391, 0.000000, 542.994141, 0.000000, 542.994141, 0.000000, 542.994141, 0.000000,
- 542.994141, 0.000000, 553.869141, 0.000000, 559.869141, 0.000000, 565.869141, 0.000000,
- 575.337891, 0.000000, 575.337891, 0.000000, 581.337891, 0.000000, 590.806641, 0.000000,
- 596.806641, 0.000000, 609.597656, -0.451172, 606.275391, 0.000000, 612.275391, 0.000000,
- 623.150391, 0.000000, 623.150391, 0.000000, 623.150391, 0.000000, 629.150391, 0.000000,
- 640.025391, 0.000000, 640.025391, 0.000000, 643.207031, -0.451172, 640.025391, 0.000000,
- 646.025391, 0.000000, 653.994141, 0.000000, 653.994141, 0.000000, 653.994141, 0.000000,
- 653.994141, 0.000000, 664.869141, 0.000000, 670.869141, 0.000000, 678.773438, 0.263672,
- 681.744141, 0.000000, 681.744141, 0.000000, 687.744141, 0.000000, 696.462891, 0.000000,
- 696.462891, 0.000000, 704.367188, 0.263672, 707.337891, 0.000000, 707.337891, 0.000000,
- 713.337891, 0.000000, 721.306641, 0.000000, 730.968750, -0.451172, 727.822266, 0.000000,
- 733.822266, 0.000000, 742.541016, 0.000000, 742.541016, 0.000000, 753.416016, 0.000000,
- 759.416016, 0.000000, 768.134766, 0.000000, 768.134766, 0.000000, 779.009766, 0.000000,
- 785.009766, 0.000000, 793.728516, 0.000000, 793.728516, 0.000000, 804.603516, 0.000000,
- 810.603516, 0.000000, 821.343750, -0.451172, 821.478516, 0.000000, 827.478516, 0.000000,
- 836.197266, 0.000000, 836.197266, 0.000000, 836.197266, 0.000000, 836.197266, 0.000000,
- 847.072266, 0.000000, 853.072266, 0.000000, 863.947266, 0.000000, 863.947266, 0.000000,
- 867.128906, -0.451172, 863.947266, 0.000000, 869.947266, 0.000000, 875.876953, 0.000000,
- 875.876953, 0.000000, 879.626953, 0.000000, 879.626953, 0.000000, 890.501953, 0.000000,
- 896.501953, 0.000000, 903.064453, 0.000000, 903.064453, 0.000000, 903.064453, 0.000000,
- 909.064453, 0.000000, 913.423828, 0.000000, 924.298828, 0.000000, 930.298828, 0.000000,
- 934.658203, 0.000000, 942.626953, 0.000000, 948.626953, 0.000000, 955.142578, 0.000000,
- 956.748047, 0.000000, 962.748047, 0.000000, 969.263672, 0.000000, 970.623047, 0.000000,
- 976.623047, 0.000000, 983.378906, 0.263672, 983.853516, 0.164062, 987.498047, 0.000000,
- 987.498047, 0.000000, 993.498047, 0.000000, 1000.875000, 0.263672, 1004.373047, 0.000000,
- 1004.373047, 0.000000, 1004.373047, 0.000000, 1010.373047, 0.000000, 1021.113281, -0.451172,
- 1021.248047, 0.000000, 1027.248047, 0.000000, 1034.947266, -0.011719, 1038.123047, 0.000000,
- 1044.123047, 0.000000, 1050.878906, 0.263672, 1054.998047, 0.000000, 1060.998047, 0.000000,
- 1068.966797, 0.000000, 1068.966797, 0.000000, 1075.529297, 0.000000, 1075.529297, 0.000000,
- 1075.529297, 0.000000, 1081.529297, 0.000000, 1090.248047, 0.000000, 1090.248047, 0.000000,
- 1098.216797, 0.000000, 1104.216797, 0.000000, 1115.091797, 0.000000, 1115.091797, 0.000000,
- 1115.091797, 0.000000, 1121.091797, 0.000000, 1131.966797, 0.000000, 1131.966797, 0.000000,
- 1131.164062, 0.275391, 1131.638672, 0.175781, 1131.966797, 0.000000, 1131.966797, 0.000000,
- 1137.966797, 0.000000, 1144.529297, 0.000000, 1144.529297, 0.000000, 1144.529297, 0.000000,
- 1150.458984, 0.000000, 1150.458984, 0.000000, 1154.208984, 0.000000, 1154.208984, 0.000000,
- 1165.083984, 0.000000, 1171.083984, 0.000000, 1181.958984, 0.000000, 1181.958984, 0.000000,
- 1181.958984, 0.000000, 1187.958984, 0.000000, 1196.677734, 0.000000, 1196.677734, 0.000000,
- 1202.607422, 0.000000, 1202.607422, 0.000000, 1210.576172, 0.000000, 1216.576172, 0.000000,
- 1224.544922, 0.000000, 1224.544922, 0.000000, 1224.544922, 0.000000, 1224.544922, 0.000000,
- 1235.419922, 0.000000, 1241.419922, 0.000000, 1249.236328, 0.263672, 1252.294922, 0.000000,
- 1252.294922, 0.000000, 1252.294922, 0.000000, 1258.294922, 0.000000, 1262.654297, 0.000000,
- 1270.470703, 0.263672, 1273.529297, 0.000000, 1273.529297, 0.000000, 1273.529297, 0.000000,
- 1279.529297, 0.000000, 1286.285156, 0.263672, 1287.345703, 0.263672, 1290.404297, 0.000000,
- 1290.404297, 0.000000, 1290.404297, 0.000000, 1296.404297, 0.000000, 1300.763672, 0.000000,
- 1311.638672, 0.000000, 1315.388672, 0.000000, 1315.388672, 0.000000, 1325.050781, -0.451172,
- 1323.474609, -0.087891, 1321.904297, 0.000000, 1327.904297, 0.000000, 1332.263672, 0.000000,
- 1338.767578, 0.439453, 1340.232422, 0.000000, 1348.201172, 0.000000, 1351.857422, 0.000000,
- 1357.857422, 0.000000, 1362.216797, 0.000000, 1372.388672, 0.000000, 1372.388672, 0.000000,
- 1372.388672, 0.000000, 1376.748047, 0.000000, 1386.919922, 0.000000, 1386.919922, 0.000000,
- 1386.919922, 0.000000, 1391.279297, 0.000000, 1402.154297, 0.000000, 1408.154297, 0.000000,
- 1416.123047, 0.000000, 1416.123047, 0.000000, 1426.998047, 0.000000, 1432.998047, 0.000000,
- 1446.076172, 0.000000, 1446.076172, 0.000000, 1446.076172, 0.000000, 1452.076172, 0.000000,
- 1460.044922, 0.000000, 1460.044922, 0.000000, 1471.294922, 0.000000, 1471.294922, 0.000000,
- 1471.294922, 0.000000, 1477.294922, 0.000000, 1485.263672, 0.000000, 1485.263672, 0.000000,
- 1496.138672, 0.000000, 1502.138672, 0.000000, 1510.107422, 0.000000, 1510.107422, 0.000000,
- 1519.576172, 0.000000, 1525.576172, 0.000000, 1533.544922, 0.000000, 1533.544922, 0.000000,
- 1543.013672, 0.000000, 1549.013672, 0.000000, 1556.982422, 0.000000, 1556.982422, 0.000000,
- 1567.857422, 0.000000, 1567.857422, 0.000000, 1567.857422, 0.000000, 1573.857422, 0.000000,
- 1581.826172, 0.000000, 1581.826172, 0.000000, 1590.544922, 0.000000, 1590.544922, 0.000000,
- 1590.544922, 0.000000, 1590.544922, 0.000000, 1598.513672, 0.000000, 1604.513672, 0.000000,
- 1612.482422, 0.000000, 1612.482422, 0.000000, 1621.201172, 0.000000, 1621.201172, 0.000000,
- 1621.201172, 0.000000, 1621.201172, 0.000000, 1630.669922, 0.000000, 1636.669922, 0.000000,
- 1641.029297, 0.000000, 1649.748047, 0.000000, 1649.748047, 0.000000, 1655.677734, 0.000000,
- 1655.677734, 0.000000, 1663.939453, 0.263672, 1663.646484, 0.000000, 1663.646484, 0.000000,
- 1669.646484, 0.000000, 1679.308594, -0.451172, 1676.162109, 0.000000, 1682.677734, 0.000000,
- 1686.427734, 0.000000, 1686.427734, 0.000000, 1696.089844, -0.451172, 1692.943359, 0.000000,
- 1698.943359, 0.000000, 1706.314453, 0.263672, 1709.818359, 0.000000, 1715.818359, 0.000000,
- 1722.574219, 0.263672, 1726.693359, 0.000000, 1732.693359, 0.000000, 1740.392578, -0.011719,
- 1743.568359, 0.000000, 1749.568359, 0.000000, 1757.291016, -0.011719, 1760.443359, 0.000000,
- 1766.443359, 0.000000, 1774.376953, -0.011719, 1777.318359, 0.000000, 1783.318359, 0.000000,
- 1791.738281, -0.439453, 1794.193359, 0.000000, 1800.193359, 0.000000, 1808.121094, 0.263672,
- 1811.068359, 0.000000, 1817.068359, 0.000000, 1823.085938, -0.011719, 1825.037109, 0.000000,
- 1831.037109, 0.000000, 1837.078125, -0.011719, 1839.005859, 0.000000, 1845.005859, 0.000000,
- 1852.529297, 0.263672, 1852.974609, 0.000000, 1858.974609, 0.000000, 1865.941406, 0.263672,
- 1866.943359, 0.000000, 1872.943359, 0.000000, 1879.294922, 0.263672, 1880.912109, 0.000000
-
-
-
-
-
-
- 中华人民共和国 台湾 中華人民共和國 臺灣
-
-
- 0x000020BC, 0x000025DD, 0x00002149, 0x00003EA0, 0x00002400, 0x0000271B, 0x0000298C, 0x00000003,
- 0x0000267F, 0x0000410D, 0x00000003, 0x000020BC, 0x0000567E, 0x00002149, 0x00003EA0, 0x00002400,
- 0x0000271B, 0x0000299A, 0x00000003, 0x00005489, 0x000042F2
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014
-
-
-
- 0.000000, 0.000000, 12.000000, 0.000000, 24.000000, 0.000000, 36.000000, 0.000000,
- 48.000000, 0.000000, 60.000000, 0.000000, 72.000000, 0.000000, 84.000000, 0.000000,
- 87.333984, 0.000000, 99.333984, 0.000000, 111.333984, 0.000000, 114.667969, 0.000000,
- 126.667969, 0.000000, 138.667969, 0.000000, 150.667969, 0.000000, 162.667969, 0.000000,
- 174.667969, 0.000000, 186.667969, 0.000000, 198.667969, 0.000000, 202.001953, 0.000000,
- 214.001953, 0.000000, 226.001953, 0.000000
-
-
-
-
-
-
-
-
-
-
-
- शङ़ु
-
-
- 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003
-
-
-
- 0.000000, 0.000000, 7.572000, 0.000000, 15.108000, 0.000000, 15.108000, 0.000000,
- 15.108000, 0.000000
-
-
-
-
-
-
-
-
- क्ष र्क क्ष र्क
-
-
- 0x000000A2, 0x0000FFFF, 0x0000FFFF, 0x00000003, 0x00000080, 0x0000005B, 0x0000FFFF, 0x00000003,
- 0x00000080, 0x00000051, 0x00000001, 0x0000009F, 0x00000003, 0x0000009A, 0x00000051, 0x00000001,
- 0x00000080
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000006, 0x00000004, 0x00000005, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010
-
-
-
- 0.000000, 0.000000, 10.875000, 0.000000, 10.875000, 0.000000, 10.875000, 0.000000,
- 16.875000, 0.000000, 24.779297, 0.263672, 27.750000, 0.000000, 27.750000, 0.000000,
- 33.750000, 0.000000, 44.490234, -0.451172, 44.625000, 0.000000, 44.625000, 0.000000,
- 52.593750, 0.000000, 58.593750, 0.000000, 68.255859, -0.451172, 65.109375, 0.000000,
- 65.109375, 0.000000, 75.984375, 0.000000
-
-
-
-
-
-
- 마만만
-
-
- 0x00000000, 0x0000FFFF, 0x00000000, 0x0000FFFF, 0x0000FFFF, 0x00000000, 0x0000FFFF
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006
-
-
-
- 0.000000, 0.000000, 9.000000, 0.000000, 9.000000, 0.000000, 18.000000, 0.000000,
- 18.000000, 0.000000, 18.000000, 0.000000, 27.000000, 0.000000, 27.000000, 0.000000
-
-
-
-
-
-
- מָשְׁכֵנִיאַחֲרֶיךָנָּרוּצָההֱבִיאַנִיהַמֶּלֶךְחֲדָרָיונָגִילָהוְנִשְׂמְחָהבָּךְנַזְכִּירָהדֹדֶיךָמִיַּיִןמֵישָׁרִיםאֲהֵבוּךָ
-
-
- 0x0000FFFF, 0x00000055, 0x0000FFFF, 0x0000004B, 0x0000001D, 0x00000097, 0x00000021, 0x00000094,
- 0x0000001B, 0x0000002D, 0x00000027, 0x00000096, 0x0000003A, 0x0000009A, 0x0000FFFF, 0x00000066,
- 0x00000027, 0x00000097, 0x0000002F, 0x00000030, 0x00000096, 0x00000027, 0x00000099, 0x0000FFFF,
- 0x00000051, 0x00000096, 0x0000002F, 0x0000FFFF, 0x00000055, 0x00000027, 0x00000098, 0x0000001F,
- 0x0000009C, 0x0000001F, 0x00000021, 0x0000009A, 0x0000003A, 0x00000027, 0x00000096, 0x0000FFFF,
- 0x00000056, 0x00000092, 0x00000024, 0x00000099, 0x00000031, 0x0000FFFF, 0x00000054, 0x0000009A,
- 0x0000FFFF, 0x00000043, 0x00000021, 0x0000009A, 0x00000025, 0x00000092, 0x0000002F, 0x00000092,
- 0x0000FFFF, 0x00000067, 0x00000096, 0x00000031, 0x00000092, 0x00000023, 0x00000021, 0x0000009A,
- 0x0000002B, 0x00000027, 0x00000096, 0x0000001E, 0x0000009A, 0x00000031, 0x00000023, 0x00000027,
- 0x0000009A, 0x0000003A, 0x0000009A, 0x0000001F, 0x00000094, 0x00000025, 0x0000FFFF, 0x00000054,
- 0x00000098, 0x0000002B, 0x00000098, 0x0000FFFF, 0x0000005D, 0x00000099, 0x00000021, 0x00000027,
- 0x00000096, 0x00000031, 0x00000099, 0x0000001B, 0x00000027, 0x00000096, 0x0000001D, 0x00000093,
- 0x00000021, 0x00000021, 0x0000009A, 0x00000038, 0x0000FFFF, 0x0000004B, 0x0000003A, 0x0000009A,
- 0x0000FFFF, 0x0000005E, 0x0000FFFF, 0x00000055, 0x00000027, 0x00000098, 0x0000003A, 0x00000094,
- 0x00000025, 0x00000099, 0x0000001B, 0x00000027, 0x00000096, 0x00000031, 0x00000097, 0x00000029,
- 0x00000092, 0x0000FFFF, 0x00000066, 0x0000009A, 0x0000002F
-
-
-
- 0x0000007C, 0x0000007B, 0x0000007A, 0x00000079, 0x00000078, 0x00000077, 0x00000076, 0x00000075,
- 0x00000074, 0x00000073, 0x00000072, 0x00000071, 0x00000070, 0x0000006F, 0x0000006E, 0x0000006D,
- 0x0000006C, 0x0000006B, 0x0000006A, 0x00000069, 0x00000068, 0x00000067, 0x00000066, 0x00000065,
- 0x00000064, 0x00000063, 0x00000062, 0x00000061, 0x00000060, 0x0000005F, 0x0000005E, 0x0000005D,
- 0x0000005C, 0x0000005B, 0x0000005A, 0x00000059, 0x00000058, 0x00000057, 0x00000056, 0x00000055,
- 0x00000054, 0x00000053, 0x00000052, 0x00000051, 0x00000050, 0x0000004F, 0x0000004E, 0x0000004D,
- 0x0000004C, 0x0000004B, 0x0000004A, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045,
- 0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003F, 0x0000003E, 0x0000003D,
- 0x0000003C, 0x0000003B, 0x0000003A, 0x00000039, 0x00000038, 0x00000037, 0x00000036, 0x00000035,
- 0x00000034, 0x00000033, 0x00000032, 0x00000031, 0x00000030, 0x0000002F, 0x0000002E, 0x0000002D,
- 0x0000002C, 0x0000002B, 0x0000002A, 0x00000029, 0x00000028, 0x00000027, 0x00000026, 0x00000025,
- 0x00000024, 0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001F, 0x0000001E, 0x0000001D,
- 0x0000001C, 0x0000001B, 0x0000001A, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
- 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000010, 0x0000000F, 0x0000000E, 0x0000000D,
- 0x0000000C, 0x0000000B, 0x0000000A, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000005,
- 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000000
-
-
-
- 0.000000, 0.000000, 0.000000, 0.000000, 5.806641, 0.000000, 5.806641, 0.000000,
- 9.087891, 0.000000, 18.679688, 0.000000, 15.251953, 0.000000, 25.365234, 0.000000,
- 21.878906, 0.000000, 28.787109, 0.000000, 35.191406, 0.000000, 42.966797, 0.000000,
- 38.279297, 0.000000, 47.982422, 0.000000, 44.085938, 0.000000, 44.085938, 0.000000,
- 52.347656, 0.000000, 58.453125, 0.000000, 55.113281, 0.000000, 62.021484, 0.000000,
- 66.292969, 0.000000, 64.886719, 0.000000, 69.292969, 0.000000, 67.886719, 0.000000,
- 67.886719, 0.000000, 74.050781, 0.000000, 70.710938, 0.000000, 77.619141, 0.000000,
- 77.619141, 0.000000, 83.425781, 0.000000, 90.527344, 0.000000, 86.513672, 0.000000,
- 91.804688, 0.000000, 92.390625, 0.000000, 98.267578, 0.000000, 109.347656, 0.000000,
- 104.894531, 0.000000, 110.701172, 0.000000, 116.250000, 0.000000, 113.701172, 0.000000,
- 113.554688, 0.000000, 121.242188, 0.000000, 119.484375, 0.000000, 124.552734, 0.000000,
- 122.677734, 0.000000, 126.679688, 0.000000, 126.679688, 0.000000, 135.210938, 0.000000,
- 132.486328, 0.000000, 132.251953, 0.000000, 138.416016, 0.000000, 148.734375, 0.000000,
- 145.042969, 0.000000, 155.308594, 0.000000, 151.968750, 0.000000, 162.773438, 0.000000,
- 158.876953, 0.000000, 158.876953, 0.000000, 168.398438, 0.000000, 166.523438, 0.000000,
- 172.546875, 0.000000, 170.525391, 0.000000, 173.689453, 0.000000, 182.718750, 0.000000,
- 180.199219, 0.000000, 185.583984, 0.000000, 190.107422, 0.000000, 187.998047, 0.000000,
- 194.132812, 0.000000, 192.257812, 0.000000, 196.259766, 0.000000, 199.423828, 0.000000,
- 206.964844, 0.000000, 202.511719, 0.000000, 212.332031, 0.000000, 208.318359, 0.000000,
- 217.886719, 0.000000, 214.195312, 0.000000, 221.121094, 0.000000, 221.121094, 0.000000,
- 229.447266, 0.000000, 226.927734, 0.000000, 235.652344, 0.000000, 232.312500, 0.000000,
- 232.312500, 0.000000, 242.648438, 0.000000, 239.220703, 0.000000, 245.847656, 0.000000,
- 250.195312, 0.000000, 248.320312, 0.000000, 255.808594, 0.000000, 252.322266, 0.000000,
- 259.230469, 0.000000, 265.042969, 0.000000, 262.083984, 0.000000, 271.675781, 0.000000,
- 268.248047, 0.000000, 274.875000, 0.000000, 284.197266, 0.000000, 281.501953, 0.000000,
- 287.250000, 0.000000, 287.250000, 0.000000, 290.531250, 0.000000, 298.212891, 0.000000,
- 296.337891, 0.000000, 296.337891, 0.000000, 300.339844, 0.000000, 300.339844, 0.000000,
- 306.146484, 0.000000, 313.687500, 0.000000, 309.234375, 0.000000, 318.732422, 0.000000,
- 315.041016, 0.000000, 325.453125, 0.000000, 321.966797, 0.000000, 328.875000, 0.000000,
- 333.222656, 0.000000, 331.347656, 0.000000, 338.044922, 0.000000, 335.349609, 0.000000,
- 345.175781, 0.000000, 341.279297, 0.000000, 341.279297, 0.000000, 352.558594, 0.000000,
- 349.218750, 0.000000, 356.126953, 0.000000
-
-
-
-
-
-
- Ţhiş iş a ţeşţ.
-
-
- 0x00000107, 0x00000049, 0x0000004A, 0x00000104, 0x00000001, 0x0000004A, 0x00000104, 0x00000001,
- 0x00000042, 0x00000001, 0x00000108, 0x00000046, 0x00000104, 0x00000108, 0x0000000F
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E
-
-
-
- 0.000000, 0.000000, 7.356000, 0.000000, 14.340000, 0.000000, 17.832001, 0.000000,
- 22.920000, 0.000000, 25.920000, 0.000000, 29.412001, 0.000000, 34.500000, 0.000000,
- 37.500000, 0.000000, 43.500000, 0.000000, 46.500000, 0.000000, 50.411999, 0.000000,
- 56.160000, 0.000000, 61.248001, 0.000000, 65.160004, 0.000000, 68.160004, 0.000000
-
-
-
-
-
-
-
-
- فتح بینچ خلیج شیخ پہنچ
-
-
- 0x0000003B, 0x00000344, 0x000001D5, 0x00000318, 0x00000349, 0x0000007C, 0x00000003, 0x0000003D,
- 0x00000348, 0x000001D5, 0x00000346, 0x000000B5, 0x00000003, 0x0000003A, 0x00000348, 0x000001D5,
- 0x000002E3, 0x00000344, 0x00000087, 0x00000003, 0x0000003B, 0x00000344, 0x000001D5, 0x00000348,
- 0x000001E5, 0x00000347, 0x0000006E, 0x00000003, 0x0000003C, 0x00000345, 0x000001D5, 0x00000344,
- 0x0000011D
-
-
-
- 0x00000015, 0x00000014, 0x00000014, 0x00000013, 0x00000012, 0x00000012, 0x00000011, 0x00000010,
- 0x0000000F, 0x0000000F, 0x0000000E, 0x0000000E, 0x0000000D, 0x0000000C, 0x0000000B, 0x0000000B,
- 0x0000000A, 0x00000009, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000006, 0x00000005,
- 0x00000005, 0x00000004, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000001, 0x00000000,
- 0x00000000
-
-
-
- 0.000000, 0.000000, 3.205078, -11.097656, 1.406250, 0.000000, 4.558594, -1.376953,
- 9.421875, -5.273438, 7.505859, -6.843750, 11.537109, 0.000000, 12.726562, 0.000000,
- 20.455078, -4.798828, 15.357422, 0.000000, 19.289062, -13.072266, 18.509766, -1.376953,
- 22.552734, 0.000000, 23.742188, 0.000000, 30.246094, -4.798828, 25.148438, 0.000000,
- 28.300781, -1.376953, 32.917969, -13.792969, 30.158203, -7.792969, 35.208984, 0.000000,
- 36.398438, 0.000000, 39.603516, -11.097656, 37.804688, 0.000000, 45.632812, 3.181641,
- 40.957031, -1.376953, 44.853516, -6.046875, 42.457031, -5.572266, 46.066406, 0.000000,
- 47.255859, 0.000000, 49.376953, -11.396484, 48.662109, 0.000000, 52.769531, -14.332031,
- 51.814453, -1.376953, 56.789062, 0.000000
-
-
-
-
-
-
- ണു്
-
-
- 0x00000023, 0x0000003C, 0x00000045
-
-
-
- 0x00000000, 0x00000001, 0x00000002
-
-
-
- 0.000000, 0.000000, 15.117188, 0.000000, 18.503906, 0.000000, 18.503906, 0.000000
-
-
-
-
-
-
- 中華人民共和國 臺灣
-
-
- 0x00000292, 0x000024E8, 0x000002D1, 0x00001582, 0x000004A1, 0x00000650, 0x000007E2, 0x00000021,
- 0x00002395, 0x00001896
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009
-
-
-
- 0.000000, 0.000000, 12.000000, 0.000000, 24.000000, 0.000000, 36.000000, 0.000000,
- 48.000000, 0.000000, 60.000000, 0.000000, 72.000000, 0.000000, 84.000000, 0.000000,
- 90.000000, 0.000000, 102.000000, 0.000000, 114.000000, 0.000000
-
-
-
-
-
-
- ప్రకాష్
-
-
- 0x00000057, 0x0000023B, 0x0000FFFF, 0x00000125, 0x00000066, 0x00000241, 0x0000FFFF
-
-
-
- 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006
-
-
-
- 0.000000, 0.000000, 8.285156, 0.000000, 14.894531, 0.000000, 14.894531, 0.000000,
- 21.503906, 0.000000, 25.136719, 0.000000, 33.421875, 0.000000, 33.421875, 0.000000
-
-
-
-
-
-
- บทที่๑พายุไซโคลนโดโรธีอาศัยอยู่ท่ามกลางทุ่งใหญ่ในแคนซัสกับลุงเฮนรีชาวไร่และป้าเอ็มภรรยาชาวไร่บ้านของพวกเขาหลังเล็กเพราะไม้สร้างบ้านต้องขนมาด้วยเกวียนเป็นระยะทางหลายไมล์
-
-
- 0x0000009D, 0x0000009A, 0x0000009A, 0x000000B8, 0x000000C9, 0x000000D2, 0x000000A1, 0x000000B5,
- 0x000000A5, 0x000000BB, 0x000000C5, 0x0000008E, 0x000000C3, 0x00000087, 0x000000A8, 0x0000009C,
- 0x000000C3, 0x00000097, 0x000000C3, 0x000000A6, 0x0000009B, 0x000000B8, 0x000000B0, 0x000000B5,
- 0x000000AB, 0x000000B4, 0x000000A5, 0x000000B0, 0x000000A5, 0x000000BC, 0x0000006E, 0x0000009A,
- 0x0000006E, 0x000000B5, 0x000000A4, 0x00000084, 0x000000A8, 0x000000B5, 0x0000008A, 0x0000009A,
- 0x000000BB, 0x0000006E, 0x0000008A, 0x000000C4, 0x000000AE, 0x00000090, 0x0000006E, 0x000000C4,
- 0x0000009C, 0x000000C2, 0x00000087, 0x0000009C, 0x0000008E, 0x000000B4, 0x000000AD, 0x00000084,
- 0x000000B4, 0x0000009D, 0x000000A8, 0x000000BB, 0x0000008A, 0x000000C1, 0x000000B1, 0x0000009C,
- 0x000000A6, 0x000000B8, 0x0000008D, 0x000000B5, 0x000000AA, 0x000000C5, 0x000000A6, 0x0000006E,
- 0x000000C2, 0x000000A8, 0x000000B3, 0x0000009E, 0x0000006F, 0x000000B5, 0x000000C1, 0x000000B0,
- 0x000000C8, 0x000000A4, 0x000000A3, 0x000000A6, 0x000000A6, 0x000000A5, 0x000000B5, 0x0000008D,
- 0x000000B5, 0x000000AA, 0x000000C5, 0x000000A6, 0x0000006E, 0x0000009D, 0x0000006F, 0x000000B5,
- 0x0000009C, 0x00000085, 0x000000B0, 0x0000008A, 0x000000A1, 0x000000AA, 0x00000084, 0x000000C1,
- 0x00000085, 0x000000B5, 0x000000AE, 0x000000A8, 0x000000B4, 0x0000008A, 0x000000C1, 0x000000A8,
- 0x000000C8, 0x00000084, 0x000000C1, 0x000000A1, 0x000000A6, 0x000000B5, 0x000000B3, 0x000000C5,
- 0x000000A4, 0x0000006F, 0x000000AD, 0x000000A6, 0x0000006F, 0x000000B5, 0x0000008A, 0x0000009D,
- 0x0000006F, 0x000000B5, 0x0000009C, 0x00000098, 0x0000006F, 0x000000B0, 0x0000008A, 0x00000085,
- 0x0000009C, 0x000000A4, 0x000000B5, 0x00000097, 0x0000006F, 0x000000AA, 0x000000A5, 0x000000C1,
- 0x00000084, 0x000000AA, 0x000000B8, 0x000000A5, 0x0000009C, 0x000000C1, 0x0000009E, 0x000000C8,
- 0x0000009C, 0x000000A6, 0x000000B3, 0x000000A5, 0x000000B3, 0x0000009A, 0x000000B5, 0x0000008A,
- 0x000000AE, 0x000000A8, 0x000000B5, 0x000000A5, 0x000000C5, 0x000000A4, 0x000000A8, 0x00000072
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F,
- 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027,
- 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F,
- 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037,
- 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F,
- 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047,
- 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F,
- 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057,
- 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F,
- 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067,
- 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F,
- 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077,
- 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F,
- 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087,
- 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F,
- 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097,
- 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F,
- 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7
-
-
-
- 0.000000, 0.000000, 5.399414, 0.000000, 10.798828, 0.000000, 15.072266, 0.000000,
- 15.072266, 0.000000, 16.198242, 0.000000, 21.046875, 0.000000, 26.616211, 0.000000,
- 30.035156, 0.000000, 31.312500, 0.000000, 34.151367, 0.000000, 38.279297, 0.000000,
- 43.558594, 0.000000, 47.663086, 0.000000, 52.438477, 0.000000, 57.178711, 0.000000,
- 62.698242, 0.000000, 66.802734, 0.000000, 71.601562, 0.000000, 75.706055, 0.000000,
- 79.810547, 0.000000, 84.029297, 0.000000, 84.369141, 0.000000, 89.097656, 0.000000,
- 92.516602, 0.000000, 97.614258, 0.000000, 97.195312, 0.000000, 101.311523, 0.000000,
- 106.040039, 0.000000, 107.375977, 0.000000, 108.326172, -0.084961, 110.156250, 0.000000,
- 113.497070, -0.084961, 115.555664, 0.000000, 118.974609, 0.000000, 124.013672, 0.000000,
- 128.765625, 0.000000, 133.505859, 0.000000, 136.924805, 0.000000, 140.704102, 0.000000,
- 143.036133, 0.000000, 144.044922, -0.084961, 146.103516, 0.000000, 149.882812, 0.000000,
- 153.553711, 0.000000, 159.158203, 0.000000, 163.377930, -0.084961, 165.421875, 0.000000,
- 169.092773, 0.000000, 174.612305, 0.000000, 179.135742, 0.000000, 183.911133, 0.000000,
- 189.430664, 0.000000, 194.879883, 0.000000, 194.709961, 0.000000, 199.989258, 0.000000,
- 204.092773, -0.084961, 204.741211, 0.000000, 210.140625, 0.000000, 212.828125, 0.000000,
- 214.880859, 0.000000, 218.660156, 0.000000, 220.675781, 0.000000, 225.128906, 0.000000,
- 230.648438, 0.000000, 234.105469, 0.000000, 234.752930, 0.000000, 239.613281, 0.000000,
- 243.032227, 0.000000, 247.280273, 0.000000, 251.408203, 0.000000, 253.932617, -0.084961,
- 255.512695, 0.000000, 260.036133, 0.000000, 264.776367, 0.000000, 269.071289, 0.000000,
- 272.704102, 0.000000, 274.470703, 0.000000, 277.889648, 0.000000, 279.905273, 0.000000,
- 284.768555, 0.000000, 284.633789, 0.000000, 289.672852, 0.000000, 294.641602, 0.000000,
- 298.746094, 0.000000, 302.850586, 0.000000, 306.966797, 0.000000, 310.385742, 0.000000,
- 315.246094, 0.000000, 318.665039, 0.000000, 322.913086, 0.000000, 327.041016, 0.000000,
- 329.565430, -0.084961, 331.145508, 0.000000, 335.911133, 0.000000, 336.544922, 0.000000,
- 339.963867, 0.000000, 345.483398, 0.000000, 350.258789, 0.000000, 354.987305, 0.000000,
- 358.766602, 0.000000, 364.335938, 0.000000, 368.583984, 0.000000, 373.335938, 0.000000,
- 375.351562, 0.000000, 380.126953, 0.000000, 383.545898, 0.000000, 389.150391, 0.000000,
- 394.306641, 0.000000, 393.890625, 0.000000, 397.669922, 0.000000, 399.685547, 0.000000,
- 404.548828, 0.000000, 404.425781, 0.000000, 409.177734, 0.000000, 411.193359, 0.000000,
- 416.762695, 0.000000, 420.867188, 0.000000, 424.286133, 0.000000, 428.581055, 0.000000,
- 432.708984, 0.000000, 438.123047, 0.000000, 437.748047, 0.000000, 443.027344, 0.000000,
- 446.976562, 0.000000, 447.131836, 0.000000, 450.550781, 0.000000, 454.330078, 0.000000,
- 459.095703, 0.000000, 459.729492, 0.000000, 463.148438, 0.000000, 468.667969, 0.000000,
- 473.847656, 0.000000, 473.478516, 0.000000, 478.207031, 0.000000, 481.986328, 0.000000,
- 486.761719, 0.000000, 492.281250, 0.000000, 497.320312, 0.000000, 500.739258, 0.000000,
- 505.860352, 0.000000, 505.538086, 0.000000, 509.786133, 0.000000, 513.902344, 0.000000,
- 515.917969, 0.000000, 520.669922, 0.000000, 523.947266, 0.000000, 524.917969, 0.000000,
- 529.034180, 0.000000, 534.553711, 0.000000, 536.569336, 0.000000, 540.846680, 0.000000,
- 541.968750, 0.000000, 547.488281, 0.000000, 551.592773, 0.000000, 555.887695, 0.000000,
- 560.003906, 0.000000, 564.298828, 0.000000, 569.698242, 0.000000, 573.117188, 0.000000,
- 576.896484, 0.000000, 582.500977, 0.000000, 587.241211, 0.000000, 590.660156, 0.000000,
- 594.776367, 0.000000, 598.904297, 0.000000, 603.943359, 0.000000, 608.894531, 0.000000,
- 608.683594, 0.000000
-
-
-
-
-
-
-
-
- ﻲﺑﺮﻌﻟﺎﺑ
-
-
- 0x0000FFFF, 0x00000206, 0x000001A5, 0x000001C2, 0x000001E0, 0x000001F3, 0x000001A2, 0x000001A5
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007
-
-
-
- 0.000000, 0.000000, 0.000000, 0.000000, 5.759766, 0.000000, 7.980469, 0.000000,
- 11.748047, 0.000000, 15.298828, 0.000000, 17.302734, 0.000000, 19.763672, 0.000000,
- 21.984375, 0.000000
-
-
-
-
-
-
- ﻲﺑﺮﻌﻟﺎﺑ
-
-
- 0x000001A5, 0x000001A2, 0x000001F3, 0x000001E0, 0x000001C2, 0x000001A5, 0x00000206
-
-
-
- 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x00000000
-
-
-
- 0.000000, 0.000000, 2.220703, 0.000000, 4.681641, 0.000000, 6.685547, 0.000000,
- 10.236328, 0.000000, 14.003906, 0.000000, 16.224609, 0.000000, 21.984375, 0.000000
-
-
-
-
-
-
- ḤḤ
-
-
- 0x000009A3, 0x000009A3
-
-
-
- 0x00000000, 0x00000001
-
-
-
- 0.000000, 0.000000, 8.666016, 0.000000, 17.332031, 0.000000
-
-
-
-
-
-
- र्य र्य
-
-
- 0x00000099, 0x0000005B, 0x0000FFFF, 0x00000003, 0x0000009A, 0x00000051, 0x00000001, 0x00000099
-
-
-
- 0x00000002, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007
-
-
-
- 0.000000, 0.000000, 9.726562, 0.263672, 9.468750, 0.000000, 9.468750, 0.000000,
- 15.468750, 0.000000, 25.130859, -0.451172, 21.984375, 0.000000, 21.984375, 0.000000,
- 31.453125, 0.000000
-
-
-
-
-
-
-
-
-
-
- Li kien kien, li kieku kieku.
-
-
- 0x0000000D, 0x00000024, 0x00000001, 0x00000026, 0x00000024, 0x00000020, 0x00000029, 0x00000001,
- 0x00000026, 0x00000024, 0x00000020, 0x00000029, 0x000001D0, 0x00000001, 0x00000027, 0x00000024,
- 0x00000001, 0x00000026, 0x00000024, 0x00000020, 0x00000026, 0x00000030, 0x00000001, 0x00000026,
- 0x00000024, 0x00000020, 0x00000026, 0x00000030, 0x000001CF
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C
-
-
-
- 0.000000, 0.000000, 7.200000, 0.000000, 14.400000, 0.000000, 21.599998, 0.000000,
- 28.799999, 0.000000, 36.000000, 0.000000, 43.200001, 0.000000, 50.400002, 0.000000,
- 57.600002, 0.000000, 64.800003, 0.000000, 72.000000, 0.000000, 79.199997, 0.000000,
- 86.399994, 0.000000, 93.599991, 0.000000, 100.799988, 0.000000, 107.999985, 0.000000,
- 115.199982, 0.000000, 122.399979, 0.000000, 129.599976, 0.000000, 136.799973, 0.000000,
- 143.999969, 0.000000, 151.199966, 0.000000, 158.399963, 0.000000, 165.599960, 0.000000,
- 172.799957, 0.000000, 179.999954, 0.000000, 187.199951, 0.000000, 194.399948, 0.000000,
- 201.599945, 0.000000, 208.799942, 0.000000
-
-
-
-
-
-
- Il-Mistoqsija oħt l-għerf.
-
-
- 0x0000000A, 0x00000027, 0x00000210, 0x0000000E, 0x00000024, 0x0000002E, 0x0000002F, 0x0000002A,
- 0x0000002C, 0x0000002E, 0x00000024, 0x00000025, 0x0000001C, 0x00000001, 0x0000002A, 0x0000011F,
- 0x0000002F, 0x00000001, 0x00000027, 0x00000210, 0x00000022, 0x0000011F, 0x00000020, 0x0000002D,
- 0x00000021, 0x000001FB
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
- 0x00000018, 0x00000019
-
-
-
- 0.000000, 0.000000, 3.096000, 0.000000, 6.156000, 0.000000, 9.888000, 0.000000,
- 18.552000, 0.000000, 21.504000, 0.000000, 26.532000, 0.000000, 30.467999, 0.000000,
- 36.972000, 0.000000, 43.571999, 0.000000, 48.599998, 0.000000, 51.551998, 0.000000,
- 54.515999, 0.000000, 60.660000, 0.000000, 63.084000, 0.000000, 69.587997, 0.000000,
- 76.115997, 0.000000, 80.171997, 0.000000, 82.596001, 0.000000, 85.655998, 0.000000,
- 89.388000, 0.000000, 95.435997, 0.000000, 101.963997, 0.000000, 107.916000, 0.000000,
- 112.080002, 0.000000, 114.984001, 0.000000, 117.972000, 0.000000
-
-
-
-
-
-
- ༄༅།། ཏིན་ཏིན་གྱི་དཔའ་རྩལ
-
-
- 0x00000145, 0x0000FFFF, 0x00000151, 0x00000151, 0x00000003, 0x0000046C, 0x00000BFD, 0x0000059A,
- 0x0000014E, 0x0000046C, 0x00000BFD, 0x0000059A, 0x0000014E, 0x000002CA, 0x0000FFFF, 0x00000BFD,
- 0x0000014E, 0x0000050E, 0x00000611, 0x00000848, 0x0000014E, 0x0000093C, 0x0000FFFF, 0x0000098B
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
- 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017
-
-
-
- 0.000000, 0.000000, 14.906250, 0.000000, 14.906250, 0.000000, 17.648438, 0.000000,
- 20.390625, 0.000000, 23.906250, 0.000000, 29.109375, 0.000000, 29.109375, 0.000000,
- 34.171875, 0.000000, 35.929688, 0.000000, 41.132812, 0.000000, 41.132812, 0.000000,
- 46.195312, 0.000000, 47.953125, 0.000000, 54.773438, 0.000000, 54.773438, 0.000000,
- 54.773438, 0.000000, 56.531250, 0.000000, 61.875000, 0.000000, 67.570312, 0.000000,
- 73.195312, 0.000000, 74.953125, 0.000000, 80.437500, 0.000000, 80.437500, 0.000000,
- 87.328125, 0.000000
-
-
-
-
-
-
- ᄊᆞᆷ ᄒᆞᆫ글 ᄀᆞᇹ ᄫᆞᆼ
-
-
- 0x000044FF, 0x00004707, 0x00004859, 0x00000005, 0x0000462B, 0x00004707, 0x00004785, 0x000019B2,
- 0x00000005, 0x00004361, 0x00004707, 0x0000498D, 0x00000005, 0x000044C3, 0x00004707, 0x00004911
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F
-
-
-
- 0.000000, 0.000000, 12.000000, 0.000000, 12.000000, 0.000000, 12.000000, 0.000000,
- 14.700000, 0.000000, 26.700001, 0.000000, 26.700001, 0.000000, 26.700001, 0.000000,
- 38.700001, 0.000000, 41.400002, 0.000000, 53.400002, 0.000000, 53.400002, 0.000000,
- 53.400002, 0.000000, 56.100002, 0.000000, 68.100006, 0.000000, 68.100006, 0.000000,
- 68.100006, 0.000000
-
-
-
-
-
-
- के े
-
-
- 0x00000901, 0x00000931, 0x00000003, 0x00000956, 0x00000931
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000003
-
-
-
- 0.000000, 0.000000, 5.935547, 0.000000, 8.548828, 0.000000, 12.345703, 0.000000,
- 17.085938, 0.000000, 18.345703, 0.000000
-
-
-
-
-
-
-
- अँग्रेज़ी
-
-
- 0x000008F1, 0x000008EE, 0x000009CB, 0x0000FFFF, 0x0000FFFF, 0x00000931, 0x00000940, 0x0000FFFF,
- 0x0000092A
-
-
-
- 0x00000000, 0x00000001, 0x00000002, 0x00000004, 0x00000003, 0x00000005, 0x00000006, 0x00000007,
- 0x00000008
-
-
-
- 0.000000, 0.000000, 9.076172, 0.000000, 9.076172, 0.000000, 16.025391, 0.000000,
- 16.025391, 0.000000, 16.025391, 0.000000, 16.025391, 0.000000, 23.976562, 0.000000,
- 23.976562, 0.000000, 27.304688, 0.000000
-
-
-
-
diff --git a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java
index 19bc6d95c39..9694043d1bb 100644
--- a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java
+++ b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2026, 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
@@ -29,10 +29,14 @@
* @run main XBMDecoderTest
*/
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
+import java.util.Arrays;
import javax.swing.ImageIcon;
public class XBMDecoderTest {
@@ -57,21 +61,39 @@ public static void main(String[] args) throws Exception {
ImageIcon icon = new ImageIcon(fis.readAllBytes());
boolean isErrEmpty = errContent.toString().isEmpty();
+
if (!isErrEmpty) {
System.out.println("Expected ImageFormatException occurred.");
System.out.print(errContent);
}
-
if (validCase && !isErrEmpty) {
throw new RuntimeException("Test failed: Error stream not empty");
- } else if (!validCase && isErrEmpty) {
+ } else if (!validCase && isErrEmpty && hasPixelData(icon.getImage())) {
throw new RuntimeException("Test failed: ImageFormatException"
+ " expected but not thrown");
}
+ if (validCase && !hasPixelData(icon.getImage())) {
+ throw new RuntimeException("Test failed: the parsed image " +
+ "does not contain any pixel data");
+ }
System.out.println("PASSED\n");
} finally {
System.setErr(originalErr);
}
}
}
+
+ private static boolean hasPixelData(Image img) {
+ int w = img.getWidth(null);
+ int h = img.getHeight(null);
+ BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = bi.createGraphics();
+ g.drawImage(img, 0, 0, null);
+ g.dispose();
+ int[] pixels = bi.getRGB(0, 0, w, h, null, 0, w);
+ if (Arrays.stream(pixels).allMatch(i -> i == 0)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm
new file mode 100644
index 00000000000..5cfb8e21cf8
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm
@@ -0,0 +1,6 @@
+#define test_width 16
+#define test_height 3
+#define ht_x 1
+#define ht_y 2
+static unsigned char test_bits[] = {
+};
diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm
index c6f819582d0..1286eee1d9b 100644
--- a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm
@@ -1,3 +1,3 @@
-#define k_wt 16
-#define k_ht 1
+#define k_width 16
+#define k_height 1
k[] = { 0x10, 1234567890};
diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm
new file mode 100644
index 00000000000..714907084f2
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm
@@ -0,0 +1,3 @@
+#define test_width 16
+#define test_height 2
+static unsigned char test_bits[] = { 0x13, 0x11, 0xAB+, 0xff };
\ No newline at end of file
diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm
new file mode 100644
index 00000000000..e24bc10e9b0
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm
@@ -0,0 +1,8 @@
+#define test_width 16
+#define test_height 3
+#define ht_x 1
+#define ht_y 2
+static unsigned char test_bits[] = {
+0x20, 0x10,
+0x25, 0x01,
+0xAC, 0xab };
diff --git a/test/jdk/java/io/Console/DefaultCharsetTest.java b/test/jdk/java/io/Console/DefaultCharsetTest.java
index 0fca8a3cc3f..981d92ce282 100644
--- a/test/jdk/java/io/Console/DefaultCharsetTest.java
+++ b/test/jdk/java/io/Console/DefaultCharsetTest.java
@@ -21,33 +21,66 @@
* questions.
*/
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static jdk.test.lib.Utils.*;
/**
* @test
- * @bug 8341975 8351435
+ * @bug 8341975 8351435 8361613
* @summary Tests the default charset. It should honor `stdout.encoding`
* which should be the same as System.out.charset()
- * @modules jdk.internal.le
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=UTF-8 DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=ISO-8859-1 DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=US-ASCII DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=foo DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le DefaultCharsetTest
+ * @requires (os.family == "linux") | (os.family == "mac")
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.JDKToolFinder
+ * jdk.test.lib.process.ProcessTools
+ * @run junit DefaultCharsetTest
*/
public class DefaultCharsetTest {
- @Test
- public void testDefaultCharset() {
+ @BeforeAll
+ static void checkExpectAvailability() {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
+ }
+ @ParameterizedTest
+ @ValueSource(strings = {"UTF-8", "ISO-8859-1", "US-ASCII", "foo", ""})
+ void testDefaultCharset(String stdoutEncoding) throws Exception {
+ // invoking "expect" command
+ OutputAnalyzer oa = ProcessTools.executeProcess(
+ "expect",
+ "-n",
+ TEST_SRC + "/defaultCharset.exp",
+ TEST_CLASSES,
+ TEST_JDK + "/bin/java",
+ "-Dstdout.encoding=" + stdoutEncoding,
+ getClass().getName());
+ oa.reportDiagnosticSummary();
+ oa.shouldHaveExitValue(0);
+ }
+
+ public static void main(String... args) {
var stdoutEncoding = System.getProperty("stdout.encoding");
var sysoutCharset = System.out.charset();
var consoleCharset = System.console().charset();
- System.out.println("""
- stdout.encoding = %s
- System.out.charset() = %s
- System.console().charset() = %s
- """.formatted(stdoutEncoding, sysoutCharset.name(), consoleCharset.name()));
- assertEquals(consoleCharset, sysoutCharset,
- "Charsets for System.out and Console differ for stdout.encoding: %s".formatted(stdoutEncoding));
+ System.out.printf("""
+ stdout.encoding = %s
+ System.out.charset() = %s
+ System.console().charset() = %s
+ """, stdoutEncoding, sysoutCharset.name(), consoleCharset.name());
+ if (!consoleCharset.equals(sysoutCharset)) {
+ System.err.printf("Charsets for System.out and Console differ for stdout.encoding: %s%n", stdoutEncoding);
+ System.exit(-1);
+ }
}
}
diff --git a/test/jdk/java/io/Console/LocaleTest.java b/test/jdk/java/io/Console/LocaleTest.java
index 1cab84a9af7..e9a281749b1 100644
--- a/test/jdk/java/io/Console/LocaleTest.java
+++ b/test/jdk/java/io/Console/LocaleTest.java
@@ -21,28 +21,40 @@
* questions.
*/
-import java.io.File;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.function.Predicate;
+import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Test;
+
+import static jdk.test.lib.Utils.*;
/**
* @test
- * @bug 8330276 8351435
+ * @bug 8330276 8351435 8361613
* @summary Tests Console methods that have Locale as an argument
+ * @requires (os.family == "linux") | (os.family == "mac")
* @library /test/lib
- * @modules jdk.internal.le jdk.localedata
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.JDKToolFinder
+ * jdk.test.lib.process.ProcessTools
+ * @modules jdk.localedata
+ * @run junit LocaleTest
*/
public class LocaleTest {
- private static Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
- private static String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
+ private static final Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
+ private static final String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
// We want to limit the expected strings within US-ASCII charset, as
// the native encoding is determined as such, which is used by
// the `Process` class under jtreg environment.
- private static List EXPECTED = List.of(
+ private static final List EXPECTED = List.of(
String.format(Locale.UK, FORMAT, TODAY),
String.format(Locale.FRANCE, FORMAT, TODAY),
String.format(Locale.GERMANY, FORMAT, TODAY),
@@ -53,56 +65,61 @@ public class LocaleTest {
String.format((Locale)null, FORMAT, TODAY)
);
- public static void main(String... args) throws Throwable {
- if (args.length == 0) {
- // no arg will launch the child process that actually perform tests
- var pb = ProcessTools.createTestJavaProcessBuilder(
- "-Djdk.console=jdk.internal.le",
- "LocaleTest", "dummy");
- var input = new File(System.getProperty("test.src", "."), "input.txt");
- pb.redirectInput(input);
- var oa = ProcessTools.executeProcess(pb);
- if (oa.getExitValue() == -1) {
- System.out.println("System.console() returns null. Ignoring the test.");
- } else {
- var output = oa.asLines();
- var resultText =
- """
- Actual output: %s
- Expected output: %s
- """.formatted(output, EXPECTED);
- if (!output.equals(EXPECTED)) {
- throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
- } else {
- oa.shouldHaveExitValue(0);
- System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
- }
- }
+ @Test
+ void testLocale() throws Exception {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
+
+ // invoking "expect" command
+ OutputAnalyzer oa = ProcessTools.executeProcess(
+ "expect",
+ "-n",
+ TEST_SRC + "/locale.exp",
+ TEST_CLASSES,
+ TEST_JDK + "/bin/java",
+ getClass().getName());
+
+ var stdout =
+ oa.stdoutAsLines().stream().filter(Predicate.not(String::isEmpty)).toList();
+ var resultText =
+ """
+ Actual output: %s
+ Expected output: %s
+ """.formatted(stdout, EXPECTED);
+ if (!stdout.equals(EXPECTED)) {
+ throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
} else {
- var con = System.console();
- if (con != null) {
- // tests these additional methods that take a Locale
- con.format(Locale.UK, FORMAT, TODAY);
- con.printf("\n");
- con.printf(Locale.FRANCE, FORMAT, TODAY);
- con.printf("\n");
- con.readLine(Locale.GERMANY, FORMAT, TODAY);
- con.printf("\n");
- con.readPassword(Locale.of("es"), FORMAT, TODAY);
- con.printf("\n");
+ oa.shouldHaveExitValue(0);
+ System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
+ }
+ }
+
+ public static void main(String... args) throws Throwable {
+ var con = System.console();
+ if (con != null) {
+ // tests these additional methods that take a Locale
+ con.format(Locale.UK, FORMAT, TODAY);
+ con.printf("\n");
+ con.printf(Locale.FRANCE, FORMAT, TODAY);
+ con.printf("\n");
+ con.readLine(Locale.GERMANY, FORMAT, TODAY);
+ con.printf("\n");
+ con.readPassword(Locale.of("es"), FORMAT, TODAY);
+ con.printf("\n");
- // tests null locale
- con.format((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.printf((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.readLine((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.readPassword((Locale)null, FORMAT, TODAY);
- } else {
- // Exit with -1
- System.exit(-1);
- }
+ // tests null locale
+ con.format((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.printf((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.readLine((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.readPassword((Locale)null, FORMAT, TODAY);
+ } else {
+ // Exit with -1
+ System.exit(-1);
}
}
}
diff --git a/test/jdk/java/io/Console/ModuleSelectionTest.java b/test/jdk/java/io/Console/ModuleSelectionTest.java
index d9885699ebf..f5f02ae13f4 100644
--- a/test/jdk/java/io/Console/ModuleSelectionTest.java
+++ b/test/jdk/java/io/Console/ModuleSelectionTest.java
@@ -21,38 +21,88 @@
* questions.
*/
-/**
+/*
* @test
- * @bug 8295803 8299689 8351435
+ * @bug 8295803 8299689 8351435 8361613 8366261
* @summary Tests System.console() returns correct Console (or null) from the expected
* module.
- * @modules java.base/java.io:+open
- * @run main/othervm ModuleSelectionTest java.base
- * @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le
- * @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base
- * @run main/othervm --limit-modules java.base ModuleSelectionTest java.base
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.process.ProcessTools
+ * @run junit ModuleSelectionTest
*/
import java.io.Console;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static jdk.test.lib.Utils.*;
public class ModuleSelectionTest {
+ private static Stream options() {
+ return Stream.of(
+ Arguments.of("-Djdk.console=foo", "java.base"),
+ Arguments.of("-Djdk.console=java.base", "java.base"),
+ Arguments.of("-Djdk.console=jdk.internal.le", "jdk.internal.le"),
+ Arguments.of("--limit-modules java.base", "java.base")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("options")
+ void testNonTTY(String opts) throws Exception {
+ opts = opts +
+ " --add-opens java.base/java.io=ALL-UNNAMED ModuleSelectionTest null";
+ OutputAnalyzer output = ProcessTools.executeTestJava(opts.split(" "));
+ output.reportDiagnosticSummary();
+ output.shouldHaveExitValue(0);
+ }
+
+ @ParameterizedTest
+ @MethodSource("options")
+ void testTTY(String opts, String expected) throws Exception {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
+
+ opts = "expect -n " + TEST_SRC + "/moduleSelection.exp " +
+ TEST_CLASSES + " " +
+ expected + " " +
+ TEST_JDK + "/bin/java" +
+ " --add-opens java.base/java.io=ALL-UNNAMED "
+ + opts;
+ // invoking "expect" command
+ OutputAnalyzer output = ProcessTools.executeProcess(opts.split(" "));
+ output.reportDiagnosticSummary();
+ output.shouldHaveExitValue(0);
+ }
+
public static void main(String... args) throws Throwable {
var con = System.console();
var pc = Class.forName("java.io.ProxyingConsole");
var jdkc = Class.forName("jdk.internal.io.JdkConsole");
- var istty = (boolean)MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup())
- .findStatic(Console.class, "istty", MethodType.methodType(boolean.class))
- .invoke();
+ var lookup = MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup());
+ var istty = (boolean)lookup.findStatic(Console.class, "isStdinTty", MethodType.methodType(boolean.class))
+ .invoke() &&
+ (boolean)lookup.findStatic(Console.class, "isStdoutTty", MethodType.methodType(boolean.class))
+ .invoke();
+
var impl = con != null ? MethodHandles.privateLookupIn(pc, MethodHandles.lookup())
.findGetter(pc, "delegate", jdkc)
.invoke(con) : null;
- var expected = switch (args[0]) {
- case "java.base" -> istty ? "java.base" : "null";
- default -> args[0];
- };
+ var expected = args[0];
var actual = con == null ? "null" : impl.getClass().getModule().getName();
if (!actual.equals(expected)) {
@@ -62,7 +112,7 @@ public static void main(String... args) throws Throwable {
Actual: %s
""".formatted(expected, actual));
} else {
- System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty);
+ System.out.printf("%s is the expected implementation. (tty: %s)\n", actual, istty);
}
}
}
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties b/test/jdk/java/io/Console/defaultCharset.exp
similarity index 73%
rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties
rename to test/jdk/java/io/Console/defaultCharset.exp
index 8b51b2a9115..5b1418db28c 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/TEST.properties
+++ b/test/jdk/java/io/Console/defaultCharset.exp
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -21,4 +21,12 @@
# questions.
#
-exclusiveAccess.dirs=.
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set java [lrange $argv 1 1]
+set stdoutProp [lrange $argv 2 2]
+set clsname [lrange $argv 3 3]
+eval spawn $java -classpath $classpath $stdoutProp $clsname
+expect eof
+set result [wait]
+exit [lindex $result 3]
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties b/test/jdk/java/io/Console/locale.exp
similarity index 70%
rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties
rename to test/jdk/java/io/Console/locale.exp
index 8b51b2a9115..a88ea43feac 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/TEST.properties
+++ b/test/jdk/java/io/Console/locale.exp
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -21,4 +21,17 @@
# questions.
#
-exclusiveAccess.dirs=.
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set java [lrange $argv 1 1]
+set clsname [lrange $argv 2 2]
+eval spawn -noecho $java -classpath $classpath $clsname
+
+# sends CR 4 times (readLine x 2, readPassword x 2)
+send "\r"
+send "\r"
+send "\r"
+send "\r"
+expect eof
+set result [wait]
+exit [lindex $result 3]
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties b/test/jdk/java/io/Console/moduleSelection.exp
similarity index 75%
rename from test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties
rename to test/jdk/java/io/Console/moduleSelection.exp
index 8b51b2a9115..2b44afe72e4 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TEST.properties
+++ b/test/jdk/java/io/Console/moduleSelection.exp
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -21,4 +21,10 @@
# questions.
#
-exclusiveAccess.dirs=.
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set expected [lrange $argv 1 1]
+set java [lrange $argv 2 2]
+set opts [lrange $argv 3 end]
+eval spawn $java $opts -classpath $classpath ModuleSelectionTest $expected
+expect eof
diff --git a/test/jdk/java/io/File/MaxPath.java b/test/jdk/java/io/File/MaxPath.java
index 269b291709c..30951ac0d85 100644
--- a/test/jdk/java/io/File/MaxPath.java
+++ b/test/jdk/java/io/File/MaxPath.java
@@ -24,21 +24,14 @@
/* @test
@bug 6481955
@summary Path length less than MAX_PATH (260) works on Windows
- @library /test/lib
+ @requires (os.family == "windows")
*/
import java.io.File;
import java.io.IOException;
-import jtreg.SkippedException;
-
public class MaxPath {
public static void main(String[] args) throws Exception {
- String osName = System.getProperty("os.name");
- if (!osName.startsWith("Windows")) {
- throw new SkippedException("This test is run only on Windows");
- }
-
int MAX_PATH = 260;
String dir = new File(".").getAbsolutePath() + "\\";
String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890";
diff --git a/test/jdk/java/lang/IO/IO.java b/test/jdk/java/lang/IO/IO.java
index dbb83db5f80..2b13657b58e 100644
--- a/test/jdk/java/lang/IO/IO.java
+++ b/test/jdk/java/lang/IO/IO.java
@@ -50,10 +50,9 @@
/*
* @test
- * @bug 8305457 8342936 8351435 8344706
+ * @bug 8305457 8342936 8351435 8344706 8361613
* @summary java.lang.IO tests
* @library /test/lib
- * @modules jdk.internal.le
* @run junit IO
*/
@ExtendWith(IO.TimingExtension.class)
@@ -78,22 +77,6 @@ public static void prepareTTY() {
} catch (Exception _) { }
}
- /*
- * Unlike printTest, which tests a _default_ console that is normally
- * jdk.internal.org.jline.JdkConsoleProviderImpl, this test tests
- * jdk.internal.io.JdkConsoleImpl. Those console implementations operate
- * in different conditions and, thus, are tested separately.
- *
- * To test jdk.internal.io.JdkConsoleImpl one needs to ensure that both
- * conditions are met:
- *
- * - a non-existent console provider is requested
- * - isatty is true
- *
- * To achieve isatty, the test currently uses the EXPECT(1) Unix command,
- * which does not work for Windows. Later, a library like pty4j or JPty
- * might be used instead of EXPECT, to cover both Unix and Windows.
- */
@ParameterizedTest
@ValueSource(strings = {"println", "print"})
public void outputTestInteractive(String mode) throws Exception {
@@ -102,8 +85,6 @@ public void outputTestInteractive(String mode) throws Exception {
expect.toString(),
Path.of(testSrc, "output.exp").toAbsolutePath().toString(),
System.getProperty("test.jdk") + "/bin/java",
- "--enable-preview",
- "-Djdk.console=gibberish",
Path.of(testSrc, "Output.java").toAbsolutePath().toString(),
mode);
assertEquals(0, output.getExitValue());
@@ -130,7 +111,7 @@ public void outputTestInteractive(String mode) throws Exception {
*/
@ParameterizedTest
@MethodSource("args")
- public void inputTestInteractive(String console, String prompt) throws Exception {
+ public void inputTestInteractive(String prompt) throws Exception {
var testSrc = System.getProperty("test.src", ".");
var command = new ArrayList();
command.add(expect.toString());
@@ -138,9 +119,6 @@ public void inputTestInteractive(String console, String prompt) throws Exception
: "input";
command.add(Path.of(testSrc, expectInputName + ".exp").toAbsolutePath().toString());
command.add(System.getProperty("test.jdk") + "/bin/java");
- command.add("--enable-preview");
- if (console != null)
- command.add("-Djdk.console=" + console);
command.add(Path.of(testSrc, "Input.java").toAbsolutePath().toString());
command.add(prompt == null ? "0" : PROMPT_NONE.equals(prompt) ? "2" : "1");
command.add(String.valueOf(prompt));
@@ -152,33 +130,11 @@ public void inputTestInteractive(String console, String prompt) throws Exception
private static final String PROMPT_NONE = "prompt-none";
public static Stream args() {
- // cross product: consoles x prompts
- return Stream.of("jdk.internal.le", "gibberish").flatMap(console -> Stream.of(null, "?", "%s", PROMPT_NONE)
- .map(prompt -> new String[]{console, prompt}).map(Arguments::of));
+ // prompts
+ return Stream.of(null, "?", "%s", PROMPT_NONE).map(Arguments::of);
}
}
- @ParameterizedTest
- @ValueSource(strings = {"println", "print"})
- public void printTest(String mode) throws Exception {
- var file = Path.of(System.getProperty("test.src", "."), "Output.java")
- .toAbsolutePath().toString();
- var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file, mode);
- OutputAnalyzer output = ProcessTools.executeProcess(pb);
- assertEquals(0, output.getExitValue());
- assertTrue(output.getStderr().isEmpty());
- output.reportDiagnosticSummary();
- String out = output.getStdout();
- // The first half of the output is produced by Console, the second
- // half is produced by IO: those halves must match.
- // Executing Console and IO in the same VM (as opposed to
- // consecutive VM runs, which are cleaner) to be able to compare string
- // representation of objects.
- assertFalse(out.isBlank());
- assertEquals(out.substring(0, out.length() / 2),
- out.substring(out.length() / 2));
- }
-
@Test //JDK-8342936
public void printlnNoParamsTest() throws Exception {
var file = Path.of("PrintlnNoParams.java");
@@ -193,7 +149,7 @@ void main() {
}
""");
}
- var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file.toString());
+ var pb = ProcessTools.createTestJavaProcessBuilder(file.toString());
OutputAnalyzer output = ProcessTools.executeProcess(pb);
assertEquals(0, output.getExitValue());
assertTrue(output.getStderr().isEmpty());
diff --git a/test/jdk/java/lang/ProcessHandle/TEST.properties b/test/jdk/java/lang/ProcessHandle/TEST.properties
new file mode 100644
index 00000000000..c7e8a6850ca
--- /dev/null
+++ b/test/jdk/java/lang/ProcessHandle/TEST.properties
@@ -0,0 +1 @@
+maxOutputSize=6000000
diff --git a/test/jdk/java/lang/String/IndexOf.java b/test/jdk/java/lang/String/IndexOf.java
index b4fd17105a8..48f23de79b0 100644
--- a/test/jdk/java/lang/String/IndexOf.java
+++ b/test/jdk/java/lang/String/IndexOf.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,15 @@
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts IndexOf
*/
+/*
+ * @test
+ * @bug 8360271
+ * @summary test String indexOf() intrinsic
+ * @requires vm.cpu.features ~= ".*avx2.*"
+ * @requires vm.compiler2.enabled
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:-CompactStrings IndexOf
+ */
+
public class IndexOf {
final int scope = 32*2+16+8;
final char a, aa, b, c, d;
@@ -56,11 +65,11 @@ enum Encoding {LL, UU, UL; }
d = 'd';
break;
case UU:
- a = '\u0061';
+ a = '\u1061';
aa = a;
- b = '\u0062';
+ b = '\u1062';
c = '\u1063';
- d = '\u0064';
+ d = '\u1064';
break;
default: //case UL:
a = 'a';
@@ -73,7 +82,7 @@ enum Encoding {LL, UU, UL; }
}
// needle =~ /ab*d/
- // badNeedle =~ /ab*db*d/
+ // badNeedle =~ /ab*cb*d/
interface Append {void append(int pos, char cc);}
String newNeedle(int size, int badPosition) {
if (size<2) {throw new RuntimeException("Fix testcase "+size);}
diff --git a/test/jdk/java/lang/StringBuilder/RacingSBThreads.java b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java
index 9177f5de1aa..26f5cf9385a 100644
--- a/test/jdk/java/lang/StringBuilder/RacingSBThreads.java
+++ b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java
@@ -46,7 +46,7 @@
public class RacingSBThreads {
private static final int TIMEOUT_SEC = 1; // Duration to run each test case
- private static final int N = 10_000_000; // static number of iterations for writes and modifies
+ private static final int N = 1_000_000; // static number of iterations for writes and modifies
private static final int LEN = 100_000; // Length of initial SB
// Strings available to be used as the initial contents of a StringBuilder
diff --git a/test/jdk/java/lang/Thread/virtual/Starvation.java b/test/jdk/java/lang/Thread/virtual/Starvation.java
index 2b8da5fbca8..987c54c1a0c 100644
--- a/test/jdk/java/lang/Thread/virtual/Starvation.java
+++ b/test/jdk/java/lang/Thread/virtual/Starvation.java
@@ -25,7 +25,7 @@
* @requires vm.continuations
* @library /test/lib
* @bug 8345294
- * @run main/othervm/timeout=200/native --enable-native-access=ALL-UNNAMED Starvation 100000
+ * @run main/othervm/native --enable-native-access=ALL-UNNAMED Starvation
*/
import java.time.Duration;
@@ -37,9 +37,16 @@
public class Starvation {
public static void main(String[] args) throws Exception {
- int iterations = Integer.parseInt(args[0]);
+ int iterations;
+ if (args.length > 0) {
+ iterations = Integer.parseInt(args[0]);
+ } else {
+ int nprocs = Runtime.getRuntime().availableProcessors();
+ iterations = 40_000 / nprocs;
+ }
- for (int i = 0; i < iterations; i++) {
+ for (int i = 1; i <= iterations; i++) {
+ System.out.format("%s iteration %d of %d ...%n", Instant.now(), i, iterations);
var exRef = new AtomicReference();
Thread thread = Thread.startVirtualThread(() -> {
try {
diff --git a/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java
new file mode 100644
index 00000000000..1b173271a79
--- /dev/null
+++ b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2025, 2026, 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 id=parked
+ * @bug 8369227
+ * @summary Stress test untimed park after a timed park when a thread is unparked around the
+ * same time that the timeout expires.
+ * @library /test/lib
+ * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 false
+ */
+
+/*
+ * @test id=pinned
+ * @summary Stress test untimed park, while pinned, and after a timed park when a thread is
+ * unparked around the same time that the timeout expires.
+ * @library /test/lib
+ * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 true
+ */
+
+import java.time.Instant;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
+import jdk.test.lib.thread.VThreadPinner;
+
+public class ParkAfterTimedPark {
+ public static void main(String[] args) throws Exception {
+ int iterations = (args.length > 0) ? Integer.parseInt(args[0]) : 100;
+ boolean pinned = (args.length > 1) ? Boolean.parseBoolean(args[1]) : false;
+
+ for (int i = 1; i <= iterations; i++) {
+ System.out.println(Instant.now() + " => " + i + " of " + iterations);
+ for (int timeout = 1; timeout <= 10; timeout++) {
+ test(timeout, true);
+ }
+ }
+ }
+
+ /**
+ * Creates two virtual threads. The first does a timed-park for the given time,
+ * then parks in CountDownLatch.await. A second virtual thread unparks the first
+ * around the same time that the timeout for the first expires.
+ */
+ private static void test(int millis, boolean pinned) throws Exception {
+ long nanos = TimeUnit.MILLISECONDS.toNanos(millis);
+
+ var finish = new CountDownLatch(1);
+
+ Thread thread1 = Thread.startVirtualThread(() -> {
+ LockSupport.parkNanos(nanos);
+ boolean done = false;
+ while (!done) {
+ try {
+ if (pinned) {
+ VThreadPinner.runPinned(() -> {
+ finish.await();
+ });
+ } else {
+ finish.await();
+ }
+ done = true;
+ } catch (InterruptedException e) { }
+ }
+ });
+
+ Thread thread2 = Thread.startVirtualThread(() -> {
+ int delta = ThreadLocalRandom.current().nextInt(millis);
+ boolean done = false;
+ while (!done) {
+ try {
+ Thread.sleep(millis - delta);
+ done = true;
+ } catch (InterruptedException e) { }
+ }
+ LockSupport.unpark(thread1);
+ });
+
+ // wait for first thread to park before count down
+ await(thread1, Thread.State.WAITING);
+ finish.countDown();
+
+ thread1.join();
+ thread2.join();
+ }
+
+ /**
+ * Waits for the given thread to reach a given state.
+ */
+ private static void await(Thread thread, Thread.State expectedState) throws Exception {
+ Thread.State state = thread.getState();
+ while (state != expectedState) {
+ if (state == Thread.State.TERMINATED)
+ throw new RuntimeException("Thread has terminated");
+ Thread.sleep(10);
+ state = thread.getState();
+ }
+ }
+}
diff --git a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java
index 6a81a7c5fee..704e299ad8b 100644
--- a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java
+++ b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java
@@ -94,17 +94,20 @@ static void test(boolean notify, boolean interrupt, int... timeouts) throws Exce
// start thread to Object.notifyAll at around time that the timeout expires
if (notify) {
- if (ThreadLocalRandom.current().nextBoolean()) {
- synchronized (lock) {
+ executor.submit(() -> {
+ if (ThreadLocalRandom.current().nextBoolean()) {
+ synchronized (lock) {
+ sleepLessThan(timeout);
+ lock.notifyAll();
+ }
+ } else {
sleepLessThan(timeout);
- lock.notifyAll();
- }
- } else {
- sleepLessThan(timeout);
- synchronized (lock) {
- lock.notifyAll();
+ synchronized (lock) {
+ lock.notifyAll();
+ }
}
- }
+ return null;
+ });
}
// start thread to interrupt first thread at around time that the timeout expires
diff --git a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java
index ccd97f82e9b..0a1ae5914ca 100644
--- a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java
+++ b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -37,7 +37,7 @@
import java.util.List;
import static java.lang.invoke.MethodHandles.lookup;
-import static org.testng.Assert.assertSame;
+import static org.testng.Assert.*;
public class TestVHInvokerCaching {
@@ -74,7 +74,7 @@ class Holder {
MethodHandles.Lookup lookup = lookup();
- for (Field field : Holder.class.getFields()) {
+ for (Field field : Holder.class.getDeclaredFields()) {
String fieldName = field.getName();
Class> fieldType = field.getType();
@@ -82,6 +82,8 @@ class Holder {
testHandles.add(lookup.findVarHandle(Holder.class, fieldName, fieldType));
}
+ assertFalse(testHandles.isEmpty());
+
return testHandles.stream().map(vh -> new Object[]{ vh }).toArray(Object[][]::new);
}
}
diff --git a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java
index 801f2e5fca6..e023a3a5839 100644
--- a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java
+++ b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -28,7 +28,7 @@
* @library /test/lib
* @build ModulesInCustomFileSystem m1/* m2/*
* jdk.test.lib.util.JarUtils
- * @run testng/othervm ModulesInCustomFileSystem
+ * @run testng/othervm -Djava.io.tmpdir=. ModulesInCustomFileSystem
* @summary Test ModuleFinder to find modules in a custom file system
*/
diff --git a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java
index 9034cf9f28a..abc1748e3f2 100644
--- a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java
+++ b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java
@@ -351,7 +351,14 @@ URI getURI() {
if (!started.get()) {
throw new IllegalStateException("Not yet started");
}
- return URI.create("ws://localhost:" + address.getPort());
+ String ip = address.getAddress().isAnyLocalAddress()
+ ? InetAddress.getLoopbackAddress().getHostAddress()
+ : address.getAddress().getHostAddress();
+ if (ip.indexOf(':') >= 0) {
+ ip = String.format("[%s]", ip);
+ }
+
+ return URI.create("ws://" + ip + ":" + address.getPort());
}
private boolean readRequest(SocketChannel channel, StringBuilder request)
diff --git a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java
index ac577069b70..ab44fba5ecd 100644
--- a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java
+++ b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -25,6 +25,11 @@
* @test
* @bug 8151299 8164704
* @modules java.net.http/jdk.internal.net.http
- * @run testng java.net.http/jdk.internal.net.http.RawChannelTest
+ * @run testng/othervm java.net.http/jdk.internal.net.http.RawChannelTest
*/
+// use
+// @run testng/othervm -Dseed=6434511950803022575
+// java.net.http/jdk.internal.net.http.RawChannelTest
+// to reproduce a failure with a particular seed (e.g. 6434511950803022575)
+// if this test is observed failing with that seed
//-Djdk.internal.httpclient.websocket.debug=true
diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java
index 9b5764735b2..f6bcdcb4d33 100644
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -23,6 +23,7 @@
package jdk.internal.net.http;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -43,8 +44,9 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
+import java.util.concurrent.atomic.AtomicReference;
+
import jdk.internal.net.http.websocket.RawChannel;
-import jdk.internal.net.http.websocket.WebSocketRequest;
import org.testng.annotations.Test;
import static java.net.http.HttpResponse.BodyHandlers.discarding;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -57,6 +59,20 @@
*/
public class RawChannelTest {
+ // can't use jdk.test.lib when injected in java.net.httpclient
+ // Seed can be specified on the @run line with -Dseed=
+ private static class RandomFactory {
+ private static long getSeed() {
+ long seed = Long.getLong("seed", new Random().nextLong());
+ System.out.println("Seed from RandomFactory = "+seed+"L");
+ return seed;
+ }
+ public static Random getRandom() {
+ return new Random(getSeed());
+ }
+ }
+
+ private static final Random RANDOM = RandomFactory.getRandom();
private final AtomicLong clientWritten = new AtomicLong();
private final AtomicLong serverWritten = new AtomicLong();
private final AtomicLong clientRead = new AtomicLong();
@@ -90,7 +106,8 @@ public void test() throws Exception {
server.setReuseAddress(false);
server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
int port = server.getLocalPort();
- new TestServer(server).start();
+ TestServer testServer = new TestServer(server);
+ testServer.start();
final RawChannel chan = channelOf(port);
print("RawChannel is %s", String.valueOf(chan));
@@ -129,6 +146,7 @@ public void handle() {
} catch (IOException e) {
outputCompleted.completeExceptionally(e);
e.printStackTrace();
+ closeChannel(chan);
}
return;
}
@@ -145,6 +163,9 @@ public void handle() {
chan.registerEvent(this);
writeStall.countDown(); // signal send buffer is full
} catch (IOException e) {
+ print("OP_WRITE failed: " + e);
+ outputCompleted.completeExceptionally(e);
+ closeChannel(chan);
throw new UncheckedIOException(e);
}
}
@@ -168,6 +189,7 @@ public void handle() {
read = chan.read();
} catch (IOException e) {
inputCompleted.completeExceptionally(e);
+ closeChannel(chan);
e.printStackTrace();
}
if (read == null) {
@@ -179,7 +201,10 @@ public void handle() {
try {
chan.registerEvent(this);
} catch (IOException e) {
- e.printStackTrace();
+ print("OP_READ failed to register event: " + e);
+ inputCompleted.completeExceptionally(e);
+ closeChannel(chan);
+ throw new UncheckedIOException(e);
}
readStall.countDown();
break;
@@ -191,21 +216,33 @@ public void handle() {
print("OP_READ read %s bytes (%s total)", total, clientRead.get());
}
});
+
CompletableFuture.allOf(outputCompleted,inputCompleted)
.whenComplete((r,t) -> {
- try {
- print("closing channel");
- chan.close();
- } catch (IOException x) {
- x.printStackTrace();
- }
+ closeChannel(chan);
});
exit.await(); // All done, we need to compare results:
assertEquals(clientRead.get(), serverWritten.get());
assertEquals(serverRead.get(), clientWritten.get());
+ Throwable serverError = testServer.failed.get();
+ if (serverError != null) {
+ throw new AssertionError("TestServer failed: "
+ + serverError, serverError);
+ }
}
}
+ private static void closeChannel(RawChannel chan) {
+ print("closing channel");
+ try {
+ chan.close();
+ } catch (IOException x) {
+ print("Failed to close channel: " + x);
+ x.printStackTrace();
+ }
+ }
+
+
private static RawChannel channelOf(int port) throws Exception {
URI uri = URI.create("http://localhost:" + port + "/");
print("raw channel to %s", uri.toString());
@@ -237,11 +274,24 @@ private static RawChannel channelOf(int port) throws Exception {
private class TestServer extends Thread { // Powered by Slowpokes
private final ServerSocket server;
+ private final AtomicReference failed = new AtomicReference<>();
TestServer(ServerSocket server) throws IOException {
this.server = server;
}
+ private void fail(Closeable s, String actor, Throwable t) {
+ failed.compareAndSet(null, t);
+ print("Server %s got exception: %s", actor, t);
+ t.printStackTrace();
+ try {
+ s.close();
+ } catch (Exception x) {
+ print("Server %s failed to close socket: %s", actor, t);
+ }
+
+ }
+
@Override
public void run() {
try (Socket s = server.accept()) {
@@ -252,21 +302,23 @@ public void run() {
Thread reader = new Thread(() -> {
try {
+ print("Server reader started");
long n = readSlowly(is);
print("Server read %s bytes", n);
s.shutdownInput();
} catch (Exception e) {
- e.printStackTrace();
+ fail(s, "reader", e);
}
});
Thread writer = new Thread(() -> {
try {
+ print("Server writer started");
long n = writeSlowly(os);
print("Server written %s bytes", n);
s.shutdownOutput();
} catch (Exception e) {
- e.printStackTrace();
+ fail(s, "writer", e);
}
});
@@ -276,7 +328,7 @@ public void run() {
reader.join();
writer.join();
} catch (Exception e) {
- e.printStackTrace();
+ fail(server,"acceptor", e);
} finally {
exit.countDown();
}
@@ -365,6 +417,8 @@ private static void print(String format, Object... args) {
}
private static byte[] byteArrayOfSize(int bound) {
- return new byte[new Random().nextInt(1 + bound)];
+ // bound must be > 1; No need to check it,
+ // nextInt will throw IllegalArgumentException if needed
+ return new byte[RANDOM.nextInt(1, bound + 1)];
}
}
diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java
index 99a127ca5ad..934bf509d88 100644
--- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java
+++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java
@@ -40,7 +40,6 @@
* @key intermittent
*/
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -77,7 +76,7 @@ public Object[][] testCases() {
};
}
- @Test(dataProvider = "testCases", timeOut=30000)
+ @Test(dataProvider = "testCases")
public void test(String desc, List opts) throws Throwable {
String pathVar = Platform.sharedLibraryPathVariableName();
System.out.println(pathVar + "=" + libraryPath);
diff --git a/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java b/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java
index 34e343b6193..86ac5b0313b 100644
--- a/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java
+++ b/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -24,7 +24,6 @@
/* @test
* @bug 4111507
* @summary retryServerSocket should not retry on BindException
- * @author Ann Wollrath
*
* @run main/othervm AddrInUse
*/
@@ -33,75 +32,54 @@
import java.rmi.registry.LocateRegistry;
import java.rmi.server.ExportException;
-public class AddrInUse implements Runnable {
+public class AddrInUse {
- private static int port = -1;
- private static final long TIMEOUT = 10000;
-
- private boolean exportSucceeded = false;
- private Throwable exportException = null;
-
- public void run() {
-
- /*
- * Attempt to create (i.e. export) a registry on the port that
- * has already been bound, and record the result.
- */
- try {
- LocateRegistry.createRegistry(port);
- synchronized (this) {
- exportSucceeded = true;
- notifyAll();
- }
- } catch (Throwable t) {
- synchronized (this) {
- exportException = t;
- notifyAll();
- }
- }
- }
+ private static volatile Throwable registryExportFailure = null;
public static void main(String[] args) throws Exception {
- System.err.println("\nRegression test for bug 4111507\n");
-
/*
* Bind a server socket to a port.
*/
- ServerSocket server = new ServerSocket(0);
- port = server.getLocalPort();
- System.err.println("Created a ServerSocket on port " + port + "...");
-
- /*
- * Start a thread that creates a registry on the same port,
- * and analyze the result.
- */
- System.err.println("create a registry on the same port...");
- System.err.println("(should cause an ExportException)");
- AddrInUse obj = new AddrInUse();
- synchronized (obj) {
- (new Thread(obj, "AddrInUse")).start();
+ try (ServerSocket server = new ServerSocket(0)) {
+ int port = server.getLocalPort();
+ System.err.println("Created a ServerSocket on port " + port + "...");
/*
- * Don't wait forever (original bug is that the export
- * hangs).
+ * Start a thread that creates a registry on the same port,
+ * and analyze the result.
*/
- obj.wait(TIMEOUT);
+ System.err.println("create a registry on the same port...");
+ System.err.println("(should cause an ExportException)");
- if (obj.exportSucceeded) {
- throw new RuntimeException(
- "TEST FAILED: export on already-bound port succeeded");
- } else if (obj.exportException != null) {
- obj.exportException.printStackTrace();
- if (obj.exportException instanceof ExportException) {
- System.err.println("TEST PASSED");
- } else {
- throw new RuntimeException(
- "TEST FAILED: unexpected exception occurred",
- obj.exportException);
+ Thread exportRegistryThread = new Thread(() -> {
+ /*
+ * Attempt to create (i.e. export) a registry on the port that
+ * has already been bound, and record the result.
+ */
+ try {
+ LocateRegistry.createRegistry(port);
+ } catch (Throwable t) {
+ registryExportFailure = t;
}
- } else {
- throw new RuntimeException("TEST FAILED: export timed out");
+ }, "ExportRegistry-Thread");
+
+ exportRegistryThread.start();
+
+ /*
+ * Wait for the LocateRegistry.createRegistry() call to complete or
+ * if it blocks forever (due to the original bug), then let jtreg fail
+ * the test with a timeout
+ */
+ exportRegistryThread.join();
+ if (registryExportFailure == null) {
+ throw new RuntimeException(
+ "TEST FAILED: export on already-bound port succeeded");
+ }
+ if (!(registryExportFailure instanceof ExportException)) {
+ throw new RuntimeException(
+ "TEST FAILED: unexpected exception occurred", registryExportFailure);
}
+ System.err.println("TEST PASSED, received expected exception: " + registryExportFailure);
}
}
}
diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java
index 2370dcd35c4..4de6598a0f4 100644
--- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java
+++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -54,12 +54,11 @@
import java.rmi.*;
import java.rmi.server.*;
-import sun.rmi.transport.*;
-import sun.rmi.*;
import java.util.Map;
import java.io.*;
import java.lang.reflect.*;
import java.rmi.registry.*;
+import sun.rmi.transport.*;
public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak {
public CheckLeaseLeak() throws RemoteException { }
@@ -102,8 +101,6 @@ public static void main (String[] args) {
System.err.println("Created client: " + i);
JavaVM jvm = new JavaVM("LeaseLeakClient",
- " -Djava.security.policy=" +
- TestParams.defaultPolicy +
" -Drmi.registry.port=" +
registryPort,
"");
@@ -128,8 +125,8 @@ public static void main (String[] args) {
}
}
- /* numLeft should be 2 - if 11 there is a problem. */
- if (numLeft > 2) {
+ /* numLeft should be 4 - if 11 there is a problem. */
+ if (numLeft > 4) {
TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+
numLeft);
} else {
@@ -156,57 +153,51 @@ private static int getDGCLeaseTableSize () {
Field f;
try {
- f = (Field) java.security.AccessController.doPrivileged
- (new java.security.PrivilegedExceptionAction() {
- public Object run() throws Exception {
-
- ObjID dgcID = new ObjID(DGC_ID);
-
- /*
- * Construct an ObjectEndpoint containing DGC's
- * ObjID.
- */
- Class oeClass =
- Class.forName("sun.rmi.transport.ObjectEndpoint");
- Class[] constrParams =
- new Class[]{ ObjID.class, Transport.class };
- Constructor oeConstructor =
- oeClass.getDeclaredConstructor(constrParams);
- oeConstructor.setAccessible(true);
- Object oe =
- oeConstructor.newInstance(
- new Object[]{ dgcID, null });
-
- /*
- * Get Target that contains DGCImpl in ObjectTable
- */
- Class objTableClass =
- Class.forName("sun.rmi.transport.ObjectTable");
- Class getTargetParams[] = new Class[] { oeClass };
- Method objTableGetTarget =
- objTableClass.getDeclaredMethod("getTarget",
- getTargetParams);
- objTableGetTarget.setAccessible(true);
- Target dgcTarget = (Target)
- objTableGetTarget.invoke(null, new Object[]{ oe });
-
- /* get the DGCImpl from its Target */
- Method targetGetImpl =
- dgcTarget.getClass().getDeclaredMethod
+ ObjID dgcID = new ObjID(DGC_ID);
+ /*
+ * Construct an ObjectEndpoint containing DGC's
+ * ObjID.
+ */
+ Class oeClass =
+ Class.forName("sun.rmi.transport.ObjectEndpoint");
+ Class[] constrParams =
+ new Class[]{ ObjID.class, Transport.class };
+ Constructor oeConstructor =
+ oeClass.getDeclaredConstructor(constrParams);
+ oeConstructor.setAccessible(true);
+ Object oe =
+ oeConstructor.newInstance(
+ new Object[]{ dgcID, null });
+
+ /*
+ * Get Target that contains DGCImpl in ObjectTable
+ */
+ Class objTableClass =
+ Class.forName("sun.rmi.transport.ObjectTable");
+ Class getTargetParams[] = new Class[] { oeClass };
+ Method objTableGetTarget =
+ objTableClass.getDeclaredMethod("getTarget",
+ getTargetParams);
+ objTableGetTarget.setAccessible(true);
+ Target dgcTarget = (Target)
+ objTableGetTarget.invoke(null, new Object[]{ oe });
+
+ /* get the DGCImpl from its Target */
+ Method targetGetImpl =
+ dgcTarget.getClass().getDeclaredMethod
("getImpl", null);
- targetGetImpl.setAccessible(true);
- dgcImpl[0] =
- (Remote) targetGetImpl.invoke(dgcTarget, null);
+ targetGetImpl.setAccessible(true);
+ dgcImpl[0] =
+ (Remote) targetGetImpl.invoke(dgcTarget, null);
- /* Get the lease table from the DGCImpl. */
- Field reflectedLeaseTable =
- dgcImpl[0].getClass().getDeclaredField
+ /* Get the lease table from the DGCImpl. */
+ Field reflectedLeaseTable =
+ dgcImpl[0].getClass().getDeclaredField
("leaseTable");
- reflectedLeaseTable.setAccessible(true);
+ reflectedLeaseTable.setAccessible(true);
+
+ f = reflectedLeaseTable;
- return reflectedLeaseTable;
- }
- });
/**
* This is the leaseTable that will fill up with LeaseInfo
@@ -217,9 +208,6 @@ public Object run() throws Exception {
numLeaseInfosLeft = leaseTable.size();
} catch(Exception e) {
- if (e instanceof java.security.PrivilegedActionException)
- e = ((java.security.PrivilegedActionException) e).
- getException();
TestLibrary.bomb(e);
}
diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java
index d9cf9fa9e96..dd24b819146 100644
--- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java
+++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/LeaseLeakClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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,7 +27,6 @@
public class LeaseLeakClient {
public static void main(String args[]) {
- TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
try {
LeaseLeak leaseLeak = null;
diff --git a/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java b/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java
new file mode 100644
index 00000000000..0c060a45b7e
--- /dev/null
+++ b/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java
@@ -0,0 +1,120 @@
+/*
+ * 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 8244336
+ * @summary Test JCE layer algorithm restriction
+ * @library /test/lib
+ * @run main/othervm TestDisabledAlgorithms KEYSTORE.JKs true
+ * @run main/othervm TestDisabledAlgorithms keySTORE.what false
+ * @run main/othervm TestDisabledAlgorithms kEYstoRe.jceKS false
+ * @run main/othervm -Djdk.crypto.disabledAlgorithms="keystore.jkS" TestDisabledAlgorithms keySTORE.jceKs true
+ * @run main/othervm -Djdk.crypto.disabledAlgorithms="KEYstORE.what" TestDisabledAlgorithms KeYStore.JKs false
+ * @run main/othervm -Djdk.crypto.disabledAlgorithms="keystOre.jceKS" TestDisabledAlgorithms KEysTORE.JKS false
+ */
+import java.io.File;
+import java.util.List;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Provider;
+import java.security.Security;
+import jdk.test.lib.Utils;
+
+public class TestDisabledAlgorithms {
+
+ private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms";
+
+ // reuse existing JKS test keystore
+ private final static String DIR = System.getProperty("test.src", ".");
+ private static final char[] PASSWD = "passphrase".toCharArray();
+ private static final String JKS_FN = "keystore.jks";
+
+ private static void test(List algos, Provider p,
+ boolean shouldThrow) throws Exception {
+
+ for (String a : algos) {
+ System.out.println("Testing " + (p != null ? p.getName() : "") +
+ ": " + a + ", shouldThrow=" + shouldThrow);
+ if (shouldThrow) {
+ if (p == null) {
+ Utils.runAndCheckException(() -> KeyStore.getInstance(a),
+ KeyStoreException.class);
+ Utils.runAndCheckException(
+ () -> KeyStore.getInstance(new File(DIR, JKS_FN),
+ PASSWD),
+ KeyStoreException.class);
+ Utils.runAndCheckException(
+ () -> KeyStore.getInstance(new File(DIR, JKS_FN),
+ () -> {
+ return new KeyStore.PasswordProtection(PASSWD);
+ }),
+ KeyStoreException.class);
+ } else {
+ // with a provider argument
+ Utils.runAndCheckException(() -> KeyStore.getInstance(a, p),
+ KeyStoreException.class);
+ Utils.runAndCheckException(() -> KeyStore.getInstance(a,
+ p.getName()), KeyStoreException.class);
+ }
+ } else {
+ KeyStore k;
+ if (p == null) {
+ k = KeyStore.getInstance(a);
+ System.out.println("Got KeyStore w/ algo " + k.getType());
+ k = KeyStore.getInstance(new File(DIR, JKS_FN), PASSWD);
+ System.out.println("Got KeyStore w/ algo " + k.getType());
+ k = KeyStore.getInstance(new File(DIR, JKS_FN),
+ () -> {
+ return new KeyStore.PasswordProtection(PASSWD);
+ });
+ System.out.println("Got KeyStore w/ algo " + k.getType());
+ } else {
+ // with a provider argument
+ k = KeyStore.getInstance(a, p);
+ k = KeyStore.getInstance(a, p.getName());
+ System.out.println("Got KeyStore w/ algo " + k.getType());
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ String propValue = args[0];
+ System.out.println("Setting Security Prop " + PROP_NAME + " = " +
+ propValue);
+ Security.setProperty(PROP_NAME, propValue);
+
+ boolean shouldThrow = Boolean.valueOf(args[1]);
+
+ List algos = List.of("JKS", "jkS");
+ // test w/o provider
+ test(algos, null, shouldThrow);
+
+ // test w/ provider
+ Provider[] providers = Security.getProviders("KeyStore.JKS");
+ for (Provider p : providers) {
+ test(algos, p, shouldThrow);
+ }
+ }
+}
diff --git a/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java b/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java
new file mode 100644
index 00000000000..413898e0c70
--- /dev/null
+++ b/test/jdk/java/security/MessageDigest/TestDisabledAlgorithms.java
@@ -0,0 +1,93 @@
+/*
+ * 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 8244336
+ * @summary Test JCE layer algorithm restriction
+ * @library /test/lib
+ * @run main/othervm TestDisabledAlgorithms MESSAGEdigest.Sha-512 true
+ * @run main/othervm TestDisabledAlgorithms messageDIGest.what false
+ * @run main/othervm TestDisabledAlgorithms meSSagedIgest.sHA-512/224 false
+ */
+import java.util.List;
+import java.security.NoSuchAlgorithmException;
+import java.security.MessageDigest;
+import java.security.Provider;
+import java.security.Security;
+import jdk.test.lib.Utils;
+
+public class TestDisabledAlgorithms {
+
+ private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms";
+
+ private static void test(List algos, Provider p,
+ boolean shouldThrow) throws Exception {
+
+ for (String a : algos) {
+ System.out.println("Testing " + (p != null ? p.getName() : "") +
+ ": " + a + ", shouldThrow=" + shouldThrow);
+ if (shouldThrow) {
+ if (p == null) {
+ Utils.runAndCheckException(() -> MessageDigest.getInstance(a),
+ NoSuchAlgorithmException.class);
+ } else {
+ Utils.runAndCheckException(() -> MessageDigest.getInstance(a, p),
+ NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(() -> MessageDigest.getInstance(a,
+ p.getName()), NoSuchAlgorithmException.class);
+ }
+ } else {
+ MessageDigest m;
+ if (p == null) {
+ m = MessageDigest.getInstance(a);
+ } else {
+ m = MessageDigest.getInstance(a, p);
+ m = MessageDigest.getInstance(a, p.getName());
+ }
+ System.out.println("Got MessageDigest w/ algo " +
+ m.getAlgorithm());
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ String propValue = args[0];
+ System.out.println("Setting Security Prop " + PROP_NAME + " = " +
+ propValue);
+ Security.setProperty(PROP_NAME, propValue);
+
+ boolean shouldThrow = Boolean.valueOf(args[1]);
+
+ List algos = List.of("sHA-512", "shA-512",
+ "2.16.840.1.101.3.4.2.3");
+ // test w/o provider
+ test(algos, null, shouldThrow);
+
+ // test w/ provider
+ Provider[] providers = Security.getProviders("MessageDigest.SHA-512");
+ for (Provider p : providers) {
+ test(algos, p, shouldThrow);
+ }
+ }
+}
diff --git a/test/jdk/java/security/Provider/NewInstance.java b/test/jdk/java/security/Provider/NewInstance.java
index ad69f468925..547b9111682 100644
--- a/test/jdk/java/security/Provider/NewInstance.java
+++ b/test/jdk/java/security/Provider/NewInstance.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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,21 +26,34 @@
* @bug 8039853
* @summary Provider.Service.newInstance() does not work with current
JDK JGSS Mechanisms
+ * @library /test/lib
*/
-import java.security.*;
-import java.util.*;
+
+import jtreg.SkippedException;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
public class NewInstance {
public static void main(String[] args) throws Exception {
- for (Provider p : Security.getProviders()) {
+
+ System.out.println("Removing SunPCSC provider from the list (A smartcard might not be installed).");
+ final List providers = Arrays.stream(Security.getProviders())
+ .filter(provider -> !provider.getName().equals("SunPCSC"))
+ .collect(Collectors.toList());
+
+ for (Provider p : providers) {
System.out.println("---------");
System.out.println(p.getName() + ":" + p.getInfo());
- if (p.getName().equals("SunPCSC")) {
- System.out.println("A smartcard might not be installed. Skip test.");
- continue;
- }
Set set = p.getServices();
Iterator i = set.iterator();
diff --git a/test/jdk/java/security/Signature/TestDisabledAlgorithms.java b/test/jdk/java/security/Signature/TestDisabledAlgorithms.java
new file mode 100644
index 00000000000..cdecf113d80
--- /dev/null
+++ b/test/jdk/java/security/Signature/TestDisabledAlgorithms.java
@@ -0,0 +1,91 @@
+/*
+ * 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 8244336
+ * @summary Test JCE layer algorithm restriction
+ * @library /test/lib
+ * @run main/othervm TestDisabledAlgorithms SIGNATURe.sha512withRSA true
+ * @run main/othervm TestDisabledAlgorithms signaturE.what false
+ * @run main/othervm TestDisabledAlgorithms SiGnAtUrE.SHa512/224withRSA false
+ */
+import java.util.List;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.Provider;
+import java.security.Security;
+import jdk.test.lib.Utils;
+
+public class TestDisabledAlgorithms {
+
+ private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms";
+
+ private static void test(List algos, Provider p,
+ boolean shouldThrow) throws Exception {
+
+ for (String a : algos) {
+ System.out.println("Testing " + (p != null ? p.getName() : "") +
+ ": " + a + ", shouldThrow=" + shouldThrow);
+ if (shouldThrow) {
+ if (p == null) {
+ Utils.runAndCheckException(() -> Signature.getInstance(a),
+ NoSuchAlgorithmException.class);
+ } else {
+ Utils.runAndCheckException(() -> Signature.getInstance(a, p),
+ NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(() -> Signature.getInstance(a,
+ p.getName()), NoSuchAlgorithmException.class);
+ }
+ } else {
+ Signature s;
+ if (p == null) {
+ s = Signature.getInstance(a);
+ } else {
+ s = Signature.getInstance(a, p);
+ s = Signature.getInstance(a, p.getName());
+ }
+ System.out.println("Got Signature w/ algo " + s.getAlgorithm());
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ String propValue = args[0];
+ System.out.println("Setting Security Prop " + PROP_NAME + " = " +
+ propValue);
+ Security.setProperty(PROP_NAME, propValue);
+
+ boolean shouldThrow = Boolean.valueOf(args[1]);
+
+ List algos = List.of("sha512withRsa", "1.2.840.113549.1.1.13");
+ // test w/o provider
+ test(algos, null, shouldThrow);
+
+ // test w/ provider
+ Provider[] providers = Security.getProviders("Signature.SHA512withRSA");
+ for (Provider p : providers) {
+ test(algos, p, shouldThrow);
+ }
+ }
+}
diff --git a/test/jdk/java/security/cert/CertStore/NoLDAP.java b/test/jdk/java/security/cert/CertStore/NoLDAP.java
index 868411e63c4..812a978931d 100644
--- a/test/jdk/java/security/cert/CertStore/NoLDAP.java
+++ b/test/jdk/java/security/cert/CertStore/NoLDAP.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,20 +25,23 @@
* @bug 8004502
* @summary Sanity check that NoSuchAlgorithmException is thrown when requesting
* a CertStore of type "LDAP" and LDAP is not available.
+ * @library /test/lib
*/
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertStore;
import java.security.cert.LDAPCertStoreParameters;
+import jtreg.SkippedException;
public class NoLDAP {
public static void main(String[] args) throws Exception {
try {
Class.forName("javax.naming.ldap.LdapName");
- System.out.println("LDAP is present, test skipped");
- return;
- } catch (ClassNotFoundException ignore) { }
+ throw new SkippedException("LDAP is present");
+ } catch (ClassNotFoundException ignore) {
+ System.err.println("Expected: class not found exception " + ignore.getMessage());
+ }
try {
CertStore.getInstance("LDAP", new LDAPCertStoreParameters());
diff --git a/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java b/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java
new file mode 100644
index 00000000000..42abc1be2ba
--- /dev/null
+++ b/test/jdk/java/text/Format/CompactNumberFormat/TestClone.java
@@ -0,0 +1,95 @@
+/*
+ * 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 8368328
+ * @summary Tests if CompactNumberFormat.clone() creates an independent object
+ * @run junit/othervm --add-opens java.base/java.text=ALL-UNNAMED TestClone
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.text.CompactNumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+
+public class TestClone {
+ // Concurrently parse numbers using cloned instances as originally
+ // reported in the bug. This test could produce false negative results,
+ // depending on the testing environment
+ @Test
+ void randomAccessTest() {
+ var original =
+ NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
+ var threads = IntStream.range(0, 10)
+ .mapToObj(num -> new Thread(() -> {
+ var clone = (NumberFormat) original.clone();
+ for (int i = 0; i < 1000; i++) {
+ assertDoesNotThrow(() ->
+ assertEquals(num, clone.parse(String.valueOf(num)).intValue()));
+ }
+ })).toList();
+ threads.forEach(Thread::start);
+ threads.forEach(t -> {
+ try {
+ t.join();
+ } catch (InterruptedException ie) {
+ throw new RuntimeException(ie);
+ }
+ });
+ }
+
+ private static Stream referenceFields() throws ClassNotFoundException {
+ return Stream.of(
+ Arguments.of("compactPatterns", String[].class),
+ Arguments.of("symbols", DecimalFormatSymbols.class),
+ Arguments.of("decimalFormat", DecimalFormat.class),
+ Arguments.of("defaultDecimalFormat", DecimalFormat.class),
+ Arguments.of("digitList", Class.forName("java.text.DigitList"))
+ );
+ }
+ // Explicitly checks if the cloned object has its own references for
+ // "compactPatterns", "symbols", "decimalFormat", "defaultDecimalFormat",
+ // and "digitList"
+ @ParameterizedTest
+ @MethodSource("referenceFields")
+ void whiteBoxTest(String fieldName, Class> type) throws Throwable {
+ var original = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
+ var clone = original.clone();
+ var lookup = MethodHandles.privateLookupIn(CompactNumberFormat.class, MethodHandles.lookup());
+
+ assertNotSame(lookup.findGetter(CompactNumberFormat.class, fieldName, type).invoke(original),
+ lookup.findGetter(CompactNumberFormat.class, fieldName, type).invoke(clone));
+ }
+}
diff --git a/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java b/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java
new file mode 100644
index 00000000000..9cbf572f368
--- /dev/null
+++ b/test/jdk/java/text/Format/DecimalFormat/RoundingTiesNearZeroTest.java
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8369050
+ * @summary Check rounding of DecimalFormat on tie cases when the maximum
+ * fraction digits allowed is one less than the position of the first
+ * significant digit in the double.
+ * @run junit RoundingTiesNearZeroTest
+ */
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.math.RoundingMode;
+import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class RoundingTiesNearZeroTest {
+
+ // Safe to re-use since we are not testing any fast-path cases
+ // so state is irrelevant
+ private static final NumberFormat format = NumberFormat.getInstance(Locale.US);
+
+ @ParameterizedTest
+ @MethodSource("ties")
+ void roundingTieTest(RoundingMode rm, int maxDigits, double db, String expected) {
+ format.setRoundingMode(rm);
+ format.setMaximumFractionDigits(maxDigits);
+ assertEquals(expected, format.format(db), "Rounding failed under " + rm);
+ }
+
+ static Stream ties() {
+ return Stream.of(
+ // 1) String is exact as binary
+ // 0.5 -> 0.5
+ Arguments.of(RoundingMode.HALF_EVEN, 0, 0.5, "0"),
+ Arguments.of(RoundingMode.HALF_UP, 0, 0.5, "1"),
+ Arguments.of(RoundingMode.HALF_DOWN, 0, 0.5, "0"),
+ // 2) String is rounded up from binary
+ // 0.0000005 -> 4.999999999999999773740559129431293428069693618454039096832275390625E-7
+ Arguments.of(RoundingMode.HALF_EVEN, 6, 0.0000005, "0"),
+ Arguments.of(RoundingMode.HALF_UP, 6, 0.0000005, "0"),
+ Arguments.of(RoundingMode.HALF_DOWN, 6, 0.0000005, "0"),
+ // 3) String is not rounded up from binary
+ // Non-exponential notation
+ // 0.05 -> 0.05000000000000000277555756156289135105907917022705078125
+ Arguments.of(RoundingMode.HALF_EVEN, 1, 0.05, "0.1"),
+ Arguments.of(RoundingMode.HALF_UP, 1, 0.05, "0.1"),
+ Arguments.of(RoundingMode.HALF_DOWN, 1, 0.05, "0.1"),
+ // Exponential notation
+ // 0.00005 -> 0.0000500000000000000023960868011929647991564706899225711822509765625
+ Arguments.of(RoundingMode.HALF_EVEN, 4, 0.00005, "0.0001"),
+ Arguments.of(RoundingMode.HALF_UP, 4, 0.00005, "0.0001"),
+ Arguments.of(RoundingMode.HALF_DOWN, 4, 0.00005, "0.0001")
+ );
+ }
+}
diff --git a/test/jdk/java/text/Format/NumberFormat/Bug4944439.java b/test/jdk/java/text/Format/NumberFormat/Bug4944439.java
index 561052e9a95..a13a36733e2 100644
--- a/test/jdk/java/text/Format/NumberFormat/Bug4944439.java
+++ b/test/jdk/java/text/Format/NumberFormat/Bug4944439.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -23,22 +23,19 @@
/*
* @test
- * @bug 4944439
+ * @bug 4944439 8372609
* @summary Confirm that numbers where all digits after the decimal separator are 0
* and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned
* as Long(not double).
* @run junit Bug4944439
*/
-import java.text.DecimalFormat;
+import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.stream.Stream;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
@@ -47,21 +44,7 @@
public class Bug4944439 {
- // Save JVM default locale
- private static final Locale savedLocale = Locale.getDefault();
- private static final DecimalFormat df = new DecimalFormat();
-
- // Set JVM default locale to US for testing
- @BeforeAll
- static void initAll() {
- Locale.setDefault(Locale.US);
- }
-
- // Restore JVM default locale
- @AfterAll
- static void tearDownAll() {
- Locale.setDefault(savedLocale);
- }
+ private static final NumberFormat df = NumberFormat.getInstance(Locale.US);
// Check return type and value returned by DecimalFormat.parse() for longs
@ParameterizedTest
diff --git a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java
index 2ff111f0e4b..6aca6d3e477 100644
--- a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java
+++ b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java
@@ -30,7 +30,7 @@
* 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
* 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
* 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 8227313
- * 8174269
+ * 8174269 8369050
* @summary Regression tests for NumberFormat and associated classes
* @library /java/text/testlib
* @build HexDumpReader TestUtils
@@ -1853,7 +1853,7 @@ public void test4241880() {
"2%", "1%", "2%", "2%", "1%",
"0%", "0%", "1%", "1%", "1%",
"0", "2", "0.2", "0.6", "0.04",
- "0.04", "0.000", "0.002",
+ "0.04", "0.001", "0.002",
};
for (int i = 0; i < input.length; i++) {
DecimalFormat format = new DecimalFormat(pattern[i]);
diff --git a/test/jdk/java/util/Calendar/RollHoursTest.java b/test/jdk/java/util/Calendar/RollHoursTest.java
new file mode 100644
index 00000000000..2eb85caab85
--- /dev/null
+++ b/test/jdk/java/util/Calendar/RollHoursTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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 8367901
+ * @summary Ensure hour rolling is correct. Particularly, when the HOUR/HOUR_OF_DAY
+ * amount rolled would cause the calendar to originate on the same hour as before
+ * the call.
+ * @run junit RollHoursTest
+ */
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.FieldSource;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.stream.IntStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class RollHoursTest {
+
+ // Should trigger multiple full HOUR/HOUR_OF_DAY cycles
+ private static final List hours =
+ IntStream.rangeClosed(-55, 55).boxed().toList();
+ // Various calendars to test against
+ private static final List calendars = List.of(
+ // GMT, independent of daylight saving time transitions
+ new GregorianCalendar(TimeZone.getTimeZone("GMT")),
+ // Daylight saving observing calendars
+ new GregorianCalendar(TimeZone.getTimeZone("America/Chicago")),
+ new GregorianCalendar(TimeZone.getTimeZone("America/Chicago")),
+ new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")),
+ new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"))
+ );
+
+ // Reset the times of each calendar. These calendars provide testing under
+ // daylight saving transitions (or the lack thereof) and different AM/PM hours.
+ @BeforeEach
+ void clear() {
+ // Reset all calendars each iteration for clean slate
+ calendars.forEach(Calendar::clear);
+
+ // Basic test, independent of daylight saving transitions
+ calendars.get(0).set(2005, 8, 20, 12, 10, 25);
+
+ // Transition to daylight saving time (CST/CDT) ---
+ // Day of transition: 03/13/2016 (Sunday)
+ // Most interesting test case due to 2 AM skip
+ calendars.get(1).set(2016, 2, 13, 3, 30, 55);
+ // Day before transition: 03/12/2016 (Saturday)
+ calendars.get(2).set(2016, 2, 12, 15, 20, 45);
+
+ // Transition back to standard time (PST/PDT) ----
+ // Day of transition: 11/06/2016 (Sunday)
+ calendars.get(3).set(2016, 10, 6, 4, 15, 20);
+ // Day before transition: 11/05/2016 (Saturday)
+ calendars.get(4).set(2016, 10, 5, 12, 25, 30);
+ }
+
+ // Rolling the HOUR_OF_DAY field.
+ @ParameterizedTest
+ @FieldSource("hours")
+ void HourOfDayTest(int hoursToRoll) {
+ for (var cal : calendars) {
+ var savedTime = cal.getTime();
+ var savedHour = cal.get(Calendar.HOUR_OF_DAY);
+ cal.roll(Calendar.HOUR_OF_DAY, hoursToRoll);
+ assertEquals(getExpectedHour(hoursToRoll, savedHour, 24, cal, savedTime),
+ cal.get(Calendar.HOUR_OF_DAY),
+ getMessage(cal.getTimeZone(), savedTime, hoursToRoll));
+ }
+ }
+
+ // Rolling the HOUR field.
+ @ParameterizedTest
+ @FieldSource("hours")
+ void HourTest(int hoursToRoll) {
+ for (var cal : calendars) {
+ var savedTime = cal.getTime();
+ var savedHour = cal.get(Calendar.HOUR_OF_DAY);
+ cal.roll(Calendar.HOUR, hoursToRoll);
+ assertEquals(getExpectedHour(hoursToRoll, savedHour, 12, cal, savedTime),
+ cal.get(Calendar.HOUR),
+ getMessage(cal.getTimeZone(), savedTime, hoursToRoll));
+ }
+ }
+
+ // Gets the expected hour after rolling by X hours. Supports 12/24-hour cycle.
+ // Special handling for non-existent 2 AM case on transition day.
+ private static int getExpectedHour(int roll, int hour, int hourCycle, Calendar cal, Date oldDate) {
+ // For example with HOUR_OF_DAY at 15 and a 24-hour cycle
+ // For rolling forwards 50 hours -> (50 + 15) % 24 = 17
+ // For hour backwards 50 hours -> (24 + (15 - 50) % 24) % 24
+ // -> (24 - 11) % 24 = 13
+ var result = (roll >= 0 ? (hour + roll) : (hourCycle + (hour + roll) % hourCycle)) % hourCycle;
+
+ // 2 AM does not exist on transition day. Calculate normalized value accordingly
+ if (cal.getTimeZone().inDaylightTime(oldDate) && cal.get(Calendar.MONTH) == Calendar.MARCH && result == 2) {
+ return roll > 0 ? result + 1 : result - 1;
+ } else {
+ // Normal return value
+ return result;
+ }
+ }
+
+ // Get a TimeZone adapted error message
+ private static String getMessage(TimeZone tz, Date date, int hoursToRoll) {
+ var fmt = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
+ fmt.setTimeZone(tz);
+ return fmt.format(date) + " incorrectly rolled " + hoursToRoll;
+ }
+}
diff --git a/test/jdk/java/util/Locale/PreserveTagCase.java b/test/jdk/java/util/Locale/PreserveTagCase.java
index c5535e3a89f..3721067e831 100644
--- a/test/jdk/java/util/Locale/PreserveTagCase.java
+++ b/test/jdk/java/util/Locale/PreserveTagCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@ public class PreserveTagCase {
*/
@ParameterizedTest
@MethodSource("filterProvider")
- public static void testFilterTags(String ranges, List tags,
+ public void testFilterTags(String ranges, List tags,
List expected, FilteringMode mode) {
List priorityList = LanguageRange.parse(ranges);
List actual = Locale.filterTags(priorityList, tags, mode);
@@ -67,7 +67,7 @@ public static void testFilterTags(String ranges, List tags,
*/
@ParameterizedTest
@MethodSource("lookupProvider")
- public static void testLookupTag(String ranges, List tags,
+ public void testLookupTag(String ranges, List tags,
String expected) {
List priorityList = LanguageRange.parse(ranges);
String actual = Locale.lookupTag(priorityList, tags);
diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
index 750d9fae2b1..76d146afc71 100644
--- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
+++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
@@ -1 +1 @@
-tzdata2025b
+tzdata2025c
diff --git a/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java b/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java
new file mode 100644
index 00000000000..fd72b8148d2
--- /dev/null
+++ b/test/jdk/java/util/concurrent/DelayScheduler/AscendingOrderAfterReplace.java
@@ -0,0 +1,140 @@
+/*
+ * 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 8370887
+ * @summary Test that cancelling a delayed task doesn't impact the ordering that other
+ * delayed tasks execute
+ */
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+public class AscendingOrderAfterReplace {
+
+ private static final int[] DELAYS_IN_MS = { 3000, 3400, 3900, 3800, 3700, 3600, 3430, 3420, 3310, 3500, 3200 };
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 1; i < DELAYS_IN_MS.length; i++) {
+ System.out.println("=== Test " + i + " ===");
+ while (!testCancel(DELAYS_IN_MS, i)) { }
+ }
+ }
+
+ /**
+ * Schedule the delayed tasks, cancel one of them, and check that the remaining tasks
+ * execute in the ascending order of delay.
+ * @return true if the test passed, false if a retry is needed
+ * @throws RuntimeException if the test fails
+ */
+ private static boolean testCancel(int[] delays, int indexToCancel) throws Exception {
+ log("Delayed tasks: " + toString(delays));
+
+ // delayed tasks add to this queue when they execute
+ var queue = new LinkedTransferQueue();
+
+ // pool with one thread to ensure that delayed tasks don't execute concurrently
+ try (var pool = new ForkJoinPool(1)) {
+ long startNanos = System.nanoTime();
+ Future>[] futures = Arrays.stream(delays)
+ .mapToObj(d -> pool.schedule(() -> {
+ log("Triggered " + d);
+ queue.add(d);
+ }, d, MILLISECONDS))
+ .toArray(Future[]::new);
+ long endNanos = System.nanoTime();
+ log("Delayed tasks submitted");
+
+ // check submit took < min diffs between two delays
+ long submitTime = Duration.ofNanos(endNanos - startNanos).toMillis();
+ long minDiff = minDifference(delays);
+ if (submitTime >= minDiff) {
+ log("Submit took >= " + minDiff + " ms, need to retry");
+ pool.shutdownNow();
+ return false;
+ }
+
+ // give a bit of time for -delayScheduler thread to process pending tasks
+ Thread.sleep(minValue(delays) / 2);
+ log("Cancel " + delays[indexToCancel]);
+ futures[indexToCancel].cancel(true);
+ }
+
+ // delayed tasks should have executed in ascending order of their delay
+ int[] executed = queue.stream().mapToInt(Integer::intValue).toArray();
+ log("Executed: " + toString(executed));
+ if (!isAscendingOrder(executed)) {
+ throw new RuntimeException("Not in ascending order!");
+ }
+ return true;
+ }
+
+ /**
+ * Return the minimum element.
+ */
+ private static int minValue(int[] array) {
+ return IntStream.of(array).min().orElseThrow();
+ }
+
+ /**
+ * Return the minimum difference between any two elements.
+ */
+ private static int minDifference(int[] array) {
+ int[] sorted = array.clone();
+ Arrays.sort(sorted);
+ return IntStream.range(1, sorted.length)
+ .map(i -> sorted[i] - sorted[i - 1])
+ .min()
+ .orElse(0);
+ }
+
+ /**
+ * Return true if the array is in ascending order.
+ */
+ private static boolean isAscendingOrder(int[] array) {
+ return IntStream.range(1, array.length)
+ .allMatch(i -> array[i - 1] <= array[i]);
+ }
+
+ /**
+ * Returns a String containing the elements of an array in index order.
+ */
+ private static String toString(int[] array) {
+ return IntStream.of(array)
+ .mapToObj(Integer::toString)
+ .collect(Collectors.joining(", ", "[", "]"));
+ }
+
+ private static void log(String message) {
+ System.out.println(Instant.now() + " " + message);
+ }
+}
+
diff --git a/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java b/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java
new file mode 100644
index 00000000000..eb6465e9619
--- /dev/null
+++ b/test/jdk/java/util/concurrent/forkjoin/ContextClassLoaderTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 8368500
+ * @run junit/othervm ContextClassLoaderTest
+ * @summary Check the context classloader is reset
+ */
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.concurrent.Future;
+import java.util.concurrent.ForkJoinPool;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ContextClassLoaderTest {
+
+ @Test
+ void testContextClassLoaderIsSetAndRestored() throws Exception {
+ Future> future = ForkJoinPool.commonPool().submit(() -> {
+ Thread thread = Thread.currentThread();
+ ClassLoader originalCCL = thread.getContextClassLoader();
+ ClassLoader customCCL = new URLClassLoader(new URL[0], originalCCL);
+ // Set custom context classloader and verify it
+ thread.setContextClassLoader(customCCL);
+ assertSame(customCCL, thread.getContextClassLoader(), "Custom context class loader not set");
+
+ // Reset to original and verify restoration
+ thread.setContextClassLoader(originalCCL);
+ assertSame(originalCCL, thread.getContextClassLoader(), "Original context class loader not restored");
+ });
+ future.get();
+ }
+}
+
diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java
index 9422128511e..de1caaab2d9 100644
--- a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java
+++ b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java
@@ -31,9 +31,6 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
@@ -41,6 +38,7 @@
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
@@ -51,13 +49,19 @@
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import junit.framework.Test;
import junit.framework.TestSuite;
+import static java.util.concurrent.TimeUnit.*;
+
public class ForkJoinPoolTest extends JSR166TestCase {
public static void main(String[] args) {
main(suite(), args);
@@ -482,6 +486,57 @@ public void testSubmitRunnable() throws Throwable {
}
}
+ public void testCancellationExceptionInGet() throws Exception {
+ final ExecutorService e = new ForkJoinPool(1);
+ try (var cleaner = cleaner(e)) {
+ assertCancellationExceptionFrom(
+ e::submit,
+ f -> () -> f.get(1000, TimeUnit.SECONDS)
+ );
+ assertCancellationExceptionFrom(
+ e::submit,
+ f -> f::get
+ );
+ assertCancellationExceptionFrom(
+ c -> e.submit(() -> { try { c.call(); } catch (Exception ex) { throw new RuntimeException(ex); } }),
+ f -> () -> f.get(1000, TimeUnit.SECONDS)
+ );
+ assertCancellationExceptionFrom(
+ c -> e.submit(() -> { try { c.call(); } catch (Exception ex) { throw new RuntimeException(ex); } }),
+ f -> f::get
+ );
+ }
+ }
+
+ private void assertCancellationExceptionFrom(
+ Function, Future>> createTask,
+ Function, Callable>> getResult) throws Exception {
+ final var t = new AtomicReference();
+ final var c = new CountDownLatch(1); // Only used to induce WAITING state (never counted down)
+ final var task = createTask.apply(() -> {
+ try {
+ t.set(Thread.currentThread());
+ c.await();
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();;
+ }
+ return null;
+ });
+ Thread taskThread;
+ while((taskThread = t.get()) == null || taskThread.getState() != Thread.State.WAITING) {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Thread.onSpinWait();
+ }
+ task.cancel(true);
+ try {
+ getResult.apply(task).call();
+ } catch (CancellationException ce) {
+ return; // Success
+ }
+ shouldThrow();
+ }
+
/**
* Completed submit(runnable, result) returns result
*/
diff --git a/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java b/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java
new file mode 100644
index 00000000000..3505552d1b1
--- /dev/null
+++ b/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java
@@ -0,0 +1,116 @@
+/*
+ * 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 8244336
+ * @summary Test JCE layer algorithm restriction
+ * @library /test/lib
+ * @run main/othervm TestDisabledAlgorithms CIPHEr.Rsa/ECB/PKCS1Padding true
+ * @run main/othervm TestDisabledAlgorithms cipheR.rsA true
+ * @run main/othervm TestDisabledAlgorithms CIPher.what false
+ * @run main/othervm TestDisabledAlgorithms cipHER.RSA/ECB/PKCS1Padding2 false
+ */
+import java.util.List;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.Signature;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import jdk.test.lib.Utils;
+
+public class TestDisabledAlgorithms {
+
+ private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms";
+
+ private static final String TARGET = "Cipher.RSA/ECB/PKCS1Padding";
+
+ private static void test(List algos, Provider p,
+ boolean shouldThrow) throws Exception {
+
+ for (String a : algos) {
+ System.out.println("Testing " + (p != null ? p.getName() : "") +
+ ": " + a + ", shouldThrow=" + shouldThrow);
+ if (shouldThrow) {
+ if (p == null) {
+ Utils.runAndCheckException(() -> Cipher.getInstance(a),
+ NoSuchAlgorithmException.class);
+ } else {
+ Utils.runAndCheckException(() -> Cipher.getInstance(a, p),
+ NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(() -> Cipher.getInstance(a,
+ p.getName()), NoSuchAlgorithmException.class);
+
+ }
+ } else {
+ Cipher c;
+ if (p == null) {
+ c = Cipher.getInstance(a);
+ } else {
+ c = Cipher.getInstance(a, p);
+ c = Cipher.getInstance(a, p.getName());
+ }
+ System.out.println("Got cipher w/ algo " + c.getAlgorithm());
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ String propValue = args[0];
+ System.out.println("Setting Security Prop " + PROP_NAME + " = " +
+ propValue);
+ Security.setProperty(PROP_NAME, propValue);
+
+ boolean shouldThrow = Boolean.valueOf(args[1]);
+
+ List algos = List.of("Rsa/ECB/PKCS1Padding", "rSA");
+
+ // test w/o provider
+ test(algos, null, shouldThrow);
+
+ // test w/ provider
+ Provider[] providers = Security.getProviders();
+ for (Provider p : providers) {
+ if (p.getService("Cipher", "RSA/ECB/PKCS1Padding") != null) {
+ test(algos, p, shouldThrow);
+ }
+ }
+
+ // make sure NONEwithRSA signature is still available from SunJCE and
+ // SunMSCAPI (windows)
+ if (shouldThrow) {
+ System.out.println("Testing NONEwithRSA signature support");
+ for (String pn : List.of("SunJCE", "SunMSCAPI")) {
+ Provider p = Security.getProvider(pn);
+ if (p != null) {
+ Signature s = Signature.getInstance("NONEwithRSA", p);
+ System.out.println(pn + "=> yes");
+ } else {
+ System.out.println(pn + "=> skip; not found");
+ }
+ }
+ }
+ System.out.println("Done");
+ }
+}
diff --git a/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java b/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java
new file mode 100644
index 00000000000..d1d9fa7a5bb
--- /dev/null
+++ b/test/jdk/javax/crypto/Cipher/TestDisabledWithOids.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2026, 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 8375549
+ * @summary Test JCE layer algorithm restriction using algorithms w/ oids
+ * @library /test/lib
+ * @run main/othervm -Djdk.crypto.disabledAlgorithms=Cipher.DES,Cipher.RSA/ECB/PKCS1Padding TestDisabledWithOids
+ * @run main/othervm -Djdk.crypto.disabledAlgorithms=Cipher.RSA/ECB/PKCS1Padding,Cipher.DES TestDisabledWithOids
+ */
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Cipher;
+import jdk.test.lib.Utils;
+
+public class TestDisabledWithOids {
+ public static void main(String[] args) throws Exception {
+ String algo1 = "RSA/ECB/PKCS1Padding";
+ String algo2 = "DES";
+
+ Utils.runAndCheckException(() -> Cipher.getInstance(algo1),
+ NoSuchAlgorithmException.class);
+ Utils.runAndCheckException(() -> Cipher.getInstance(algo2),
+ NoSuchAlgorithmException.class);
+ System.out.println("Done");
+ }
+}
diff --git a/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java
new file mode 100644
index 00000000000..56e35f2a72a
--- /dev/null
+++ b/test/jdk/javax/crypto/Cipher/TestEmptyModePadding.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025 IBM Corporation. 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 8359388
+ * @summary test that the Cipher.getInstance() would reject improper
+ * transformations with empty mode and/or padding.
+ */
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.Cipher;
+
+public class TestEmptyModePadding {
+
+ public static void main(String[] args) throws Exception {
+ Provider provider = Security.getProvider(
+ System.getProperty("test.provider.name", "SunJCE"));
+
+ System.out.println("Testing against " + provider.getName());
+
+ String[] testTransformations = {
+ // transformations w/ only 1 component, i.e. algo
+ " ",
+ // transformations w/ only 2 components
+ "AES/",
+ "AES/ ",
+ "AES/CBC",
+ "PBEWithHmacSHA512/224AndAES_128/",
+ "PBEWithHmacSHA512/256AndAES_128/ ",
+ "PBEWithHmacSHA512/224AndAES_128/CBC",
+ // 3-component transformations w/ empty component(s)
+ "AES//",
+ "AES/ /",
+ "AES// ",
+ "AES/ / ",
+ "AES/CBC/", "AES/CBC/ ",
+ "AES//PKCS5Padding", "AES/ /NoPadding",
+ "PBEWithHmacSHA512/224AndAES_128//",
+ "PBEWithHmacSHA512/224AndAES_128/ /",
+ "PBEWithHmacSHA512/224AndAES_128// ",
+ "PBEWithHmacSHA512/224AndAES_128/ / ",
+ "PBEWithHmacSHA512/256AndAES_128/CBC/",
+ "PBEWithHmacSHA512/256AndAES_128/CBC/ ",
+ "PBEWithHmacSHA512/256AndAES_128//PKCS5Padding",
+ "PBEWithHmacSHA512/256AndAES_128/ /PKCS5Padding",
+ };
+
+ for (String t : testTransformations) {
+ test(t, provider);
+ }
+ }
+
+ private static void test(String t, Provider p) throws Exception {
+ try {
+ Cipher c = Cipher.getInstance(t, p);
+ throw new RuntimeException("Should throw NSAE for \'" + t + "\'");
+ } catch (NoSuchAlgorithmException nsae) {
+ // transformation info is already in the NSAE message
+ System.out.println("Expected NSAE: " + nsae.getMessage());
+ }
+ }
+}
diff --git a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
index b9829621d68..c34311f1689 100644
--- a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
+++ b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
@@ -33,7 +33,11 @@
* @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS
*/
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -41,7 +45,9 @@
import java.net.URL;
import java.net.HttpURLConnection;
import java.net.InetAddress;
+
import javax.net.ssl.*;
+
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.Security;
@@ -55,7 +61,16 @@
import java.security.cert.PKIXRevocationChecker;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import jdk.test.lib.security.SimpleOCSPServer;
@@ -92,10 +107,6 @@ public class HttpsUrlConnClient {
static String INT_ALIAS = "intermediate";
static String SSL_ALIAS = "ssl";
- /*
- * Is the server ready to serve?
- */
- volatile static boolean serverReady = false;
volatile int serverPort = 0;
volatile Exception serverException = null;
@@ -164,7 +175,7 @@ static void testPKIXParametersRevEnabled(String[] allowedProts)
ClientParameters cliParams = new ClientParameters();
cliParams.protocols = allowedProts;
ServerParameters servParams = new ServerParameters();
- serverReady = false;
+ CountDownLatch serverReady = new CountDownLatch(1);
System.out.println("=====================================");
System.out.println("Stapling enabled, PKIXParameters with");
@@ -192,7 +203,7 @@ static void testPKIXParametersRevEnabled(String[] allowedProts)
Security.setProperty("ocsp.enable", "false");
HttpsUrlConnClient sslTest = new HttpsUrlConnClient(cliParams,
- servParams);
+ servParams, serverReady);
TestResult tr = sslTest.getResult();
if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) {
if (tr.clientExc != null) {
@@ -219,10 +230,11 @@ static void testPKIXParametersRevEnabled(String[] allowedProts)
/*
* Define the server side of the test.
*
- * If the server prematurely exits, serverReady will be set to true
+ * If the server prematurely exits, serverReady will be counted down
* to avoid infinite hangs.
*/
- void doServerSide(ServerParameters servParams) throws Exception {
+ void doServerSide(ServerParameters servParams, CountDownLatch serverReady)
+ throws Exception {
// Selectively enable or disable the feature
System.setProperty("jdk.tls.server.enableStatusRequestExtension",
@@ -274,7 +286,7 @@ void doServerSide(ServerParameters servParams) throws Exception {
/*
* Signal Client, we're ready for his connect.
*/
- serverReady = true;
+ serverReady.countDown();
try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
BufferedReader in = new BufferedReader(
@@ -306,18 +318,13 @@ void doServerSide(ServerParameters servParams) throws Exception {
/*
* Define the client side of the test.
*
- * If the server prematurely exits, serverReady will be set to true
+ * If the server prematurely exits, serverReady will be counted down
* to avoid infinite hangs.
*/
- void doClientSide(ClientParameters cliParams) throws Exception {
+ void doClientSide(ClientParameters cliParams, CountDownLatch serverReady)
+ throws Exception {
- // Wait 5 seconds for server ready
- for (int i = 0; (i < 100 && !serverReady); i++) {
- Thread.sleep(50);
- }
- if (!serverReady) {
- throw new RuntimeException("Server not ready yet");
- }
+ serverReady.await();
// Selectively enable or disable the feature
System.setProperty("jdk.tls.client.enableStatusRequestExtension",
@@ -373,16 +380,16 @@ void doClientSide(ClientParameters cliParams) throws Exception {
*
* Fork off the other side, then do your work.
*/
- HttpsUrlConnClient(ClientParameters cliParams,
- ServerParameters servParams) throws Exception {
+ HttpsUrlConnClient(ClientParameters cliParams, ServerParameters servParams,
+ CountDownLatch serverReady) throws Exception {
Exception startException = null;
try {
if (separateServerThread) {
- startServer(servParams, true);
- startClient(cliParams, false);
+ startServer(servParams, true, serverReady);
+ startClient(cliParams, false, serverReady);
} else {
- startClient(cliParams, true);
- startServer(servParams, false);
+ startClient(cliParams, true, serverReady);
+ startServer(servParams, false, serverReady);
}
} catch (Exception e) {
startException = e;
@@ -453,51 +460,53 @@ TestResult getResult() {
return tr;
}
- final void startServer(ServerParameters servParams, boolean newThread)
- throws Exception {
+ final void startServer(ServerParameters servParams, boolean newThread,
+ CountDownLatch serverReady) throws IOException {
if (newThread) {
serverThread = new Thread() {
@Override
public void run() {
try {
- doServerSide(servParams);
+ doServerSide(servParams, serverReady);
} catch (Exception e) {
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
- System.err.println("Server died...");
- serverReady = true;
+ System.err.println("Server died: " + e);
serverException = e;
+ } finally {
+ serverReady.countDown();
}
}
};
serverThread.start();
} else {
try {
- doServerSide(servParams);
+ doServerSide(servParams, serverReady);
} catch (Exception e) {
+ System.err.println("Server died: " + e);
serverException = e;
} finally {
- serverReady = true;
+ serverReady.countDown();
}
}
}
- final void startClient(ClientParameters cliParams, boolean newThread)
- throws Exception {
+ final void startClient(ClientParameters cliParams, boolean newThread,
+ CountDownLatch serverReady) throws Exception {
if (newThread) {
clientThread = new Thread() {
@Override
public void run() {
try {
- doClientSide(cliParams);
+ doClientSide(cliParams, serverReady);
} catch (Exception e) {
/*
* Our client thread just died.
*/
- System.err.println("Client died...");
+ System.err.println("Client died: " + e);
clientException = e;
}
}
@@ -505,9 +514,10 @@ public void run() {
clientThread.start();
} else {
try {
- doClientSide(cliParams);
+ doClientSide(cliParams, serverReady);
} catch (Exception e) {
clientException = e;
+ System.err.println("Client died: " + e);
}
}
}
diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java
index 1bfc3ebcdbb..9950caf1921 100644
--- a/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java
+++ b/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 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
@@ -49,13 +49,6 @@ protected void printLog() throws IOException {
System.out.println(Utilities.readFile(logPath).orElse(""));
}
- /*
- * Deletes log file if exists.
- */
- protected void deleteLog() throws IOException {
- Utilities.deleteFile(getLogPath());
- }
-
/*
* The negotiated application protocol.
*/
diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java
index 91d1a8d1ead..7d3cb7d1665 100644
--- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java
+++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 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
@@ -148,7 +148,6 @@ protected Path getLogPath() {
@Override
public void close() throws IOException {
printLog();
- deleteLog();
}
public static void main(String[] args) throws Exception {
diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java
index b07a039203e..a6c8a13e0c6 100644
--- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java
+++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkProcServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 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
@@ -166,7 +166,6 @@ public void signalStop() {
public void close() throws IOException {
printLog();
deletePort();
- deleteLog();
}
private static int readPort() {
diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java
index 0891523ac11..51706cec927 100644
--- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java
+++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java
@@ -190,6 +190,7 @@ protected void doServerSide() throws Exception {
try {
sslServerSocket.setSoTimeout(30000);
sslSocket = (SSLSocket)sslServerSocket.accept();
+ System.out.println("Connection established on port : " +serverPort);
} catch (SocketTimeoutException ste) {
// Ignore the test case if no connection within 30 seconds.
System.out.println(
@@ -228,6 +229,7 @@ protected void doServerSide() throws Exception {
}
} finally {
sslSocket.close();
+ System.out.println("Connection closed on port : " +serverPort);
}
}
diff --git a/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java b/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java
index 27290738a0c..afac39b83fb 100644
--- a/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java
+++ b/test/jdk/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java
@@ -24,6 +24,7 @@
/**
* @test
* @bug 4933700
+ * @key sound
* @summary Tests that default devices return MidiDeviceTransmitter/Receiver and returned objects return correct MidiDevice
* @compile TestAllDevices.java
* @run main TestAllDevices
diff --git a/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java b/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java
index 00c57f46c98..7b8c4b0a3f2 100644
--- a/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java
+++ b/test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java
@@ -35,6 +35,7 @@
/**
* @test
* @bug 8074211 8237495 8301310
+ * @key sound
* @summary fail with memory errors when asked to send a sysex message starting
* with 0xF7
*/
diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java
index efb57eeeae2..05ba16cded5 100644
--- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java
+++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java
@@ -32,6 +32,7 @@
/**
* @test
* @bug 8143909
+ * @key sound
* @author Sergey Bylokhov
*/
public final class ExpectedNPEOnNull {
diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java
index 8eabb992bca..71d27c4943c 100644
--- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java
+++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java
@@ -35,6 +35,7 @@
/**
* @test
* @bug 8059743
+ * @key sound
* @summary MidiDeviceProvider shouldn't returns incorrect results in case of
* some unknown MidiDevice.Info
* @author Sergey Bylokhov
diff --git a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java
index 685a5e8af62..5d37759fbad 100644
--- a/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java
+++ b/test/jdk/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java
@@ -30,6 +30,7 @@
/**
* @test
* @bug 8058115
+ * @key sound
* @summary MidiDeviceProvider shouldn't returns incorrect results in case of
* unsupported MidiDevice.Info
* @author Sergey Bylokhov
diff --git a/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java b/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java
index c115d44edbf..8dba2ae3e08 100644
--- a/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java
+++ b/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 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
@@ -30,7 +30,6 @@
* @run main TestButtonGroupFocusTraversal
*/
-import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
@@ -43,9 +42,7 @@
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.KeyboardFocusManager;
-import java.awt.Point;
import java.awt.Robot;
-import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
public class TestButtonGroupFocusTraversal {
@@ -53,25 +50,11 @@ public class TestButtonGroupFocusTraversal {
private static JTextField textFieldFirst, textFieldLast;
private static JToggleButton toggleButton1, toggleButton2;
private static JCheckBox checkBox1, checkBox2;
- private static boolean toggleButtonActionPerformed;
- private static boolean checkboxActionPerformed;
+ private static volatile boolean toggleButtonActionPerformed;
+ private static volatile boolean checkboxActionPerformed;
private static JRadioButton radioButton1, radioButton2;
private static Robot robot;
- private static void blockTillDisplayed(Component comp) {
- Point p = null;
- while (p == null) {
- try {
- p = comp.getLocationOnScreen();
- } catch (IllegalStateException e) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- }
-
private static void createUI() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -84,33 +67,11 @@ public void run() {
checkBox1 = new JCheckBox("1");
checkBox2 = new JCheckBox("2");
- toggleButton1.setAction(new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- toggleButtonActionPerformed = true;
- }
- });
-
- toggleButton2.setAction(new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- toggleButtonActionPerformed = true;
- }
- });
-
- checkBox1.setAction(new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- checkboxActionPerformed = true;
- }
- });
-
- checkBox2.setAction(new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- checkboxActionPerformed = true;
- }
- });
+ toggleButton1.addActionListener((_) -> toggleButtonActionPerformed = true);
+ toggleButton2.addActionListener((_) -> toggleButtonActionPerformed = true);
+
+ checkBox1.addActionListener((_) -> checkboxActionPerformed = true);
+ checkBox2.addActionListener((_) -> checkboxActionPerformed = true);
ButtonGroup toggleGroup = new ButtonGroup();
toggleGroup.add(toggleButton1);
@@ -128,7 +89,7 @@ public void actionPerformed(ActionEvent e) {
radioButton2.setSelected(true);
checkBox2.setSelected(true);
- frame = new JFrame("Test");
+ frame = new JFrame("TestButtonGroupFocusTraversal");
frame.setLayout(new FlowLayout());
Container pane = frame.getContentPane();
@@ -178,7 +139,7 @@ private static void checkToggleButtonActionPerformed() {
}
private static void checkCheckboxActionPerformed() {
- if (toggleButtonActionPerformed) {
+ if (checkboxActionPerformed) {
throw new RuntimeException("Checkbox Action should not be" +
"performed");
}
@@ -196,19 +157,13 @@ public static void main(String[] args) throws Exception {
createUI();
robot.waitForIdle();
- robot.delay(200);
-
- blockTillDisplayed(frame);
+ robot.delay(500);
SwingUtilities.invokeAndWait(textFieldFirst::requestFocus);
if (!textFieldFirst.equals(KeyboardFocusManager.getCurrentKeyboardFocusManager()
.getFocusOwner())) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ robot.delay(300);
SwingUtilities.invokeAndWait(textFieldFirst::requestFocus);
}
diff --git a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java b/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java
deleted file mode 100644
index 06ccfc3b9bf..00000000000
--- a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.awt.Graphics;
-import java.awt.image.BufferedImage;
-import javax.imageio.ImageIO;
-import javax.swing.JComponent;
-import javax.swing.JProgressBar;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.UnsupportedLookAndFeelException;
-
-import static java.awt.image.BufferedImage.TYPE_INT_RGB;
-
-/*
- * @test
- * @bug 8224261
- * @key headful
- * @library ../regtesthelpers
- * @build Util
- * @summary Verifies JProgressBar border is not painted when border
- * painting is set to false
- * @run main TestProgressBarBorder
- */
-
-public class TestProgressBarBorder {
- public static void main(String[] args) throws Exception {
- for (UIManager.LookAndFeelInfo laf :
- UIManager.getInstalledLookAndFeels()) {
- if (!laf.getName().contains("Nimbus") && !laf.getName().contains("GTK")) {
- continue;
- }
- System.out.println("Testing LAF: " + laf.getName());
- SwingUtilities.invokeAndWait(() -> test(laf));
- }
- }
-
- private static void test(UIManager.LookAndFeelInfo laf) {
- setLookAndFeel(laf);
- JProgressBar progressBar = createProgressBar();
- progressBar.setBorderPainted(true);
- BufferedImage withBorder = paintToImage(progressBar);
- progressBar.setBorderPainted(false);
- BufferedImage withoutBorder = paintToImage(progressBar);
-
- boolean equal = Util.compareBufferedImages(withBorder, withoutBorder);
- if (equal) {
- try {
- ImageIO.write(withBorder, "png", new File("withBorder.png"));
- ImageIO.write(withoutBorder, "png", new File("withoutBorder.png"));
- } catch (IOException ignored) {}
-
- throw new RuntimeException("JProgressBar border is painted when border " +
- "painting is set to false");
- }
- }
-
- private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) {
- try {
- UIManager.setLookAndFeel(laf.getClassName());
- } catch (UnsupportedLookAndFeelException ignored) {
- System.out.println("Unsupported LAF: " + laf.getClassName());
- } catch (ClassNotFoundException | InstantiationException
- | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static JProgressBar createProgressBar() {
- JProgressBar progressBar = new JProgressBar();
- progressBar.setSize(100, 50);
- progressBar.setValue(0);
- progressBar.setStringPainted(true);
- return progressBar;
- }
-
- private static BufferedImage paintToImage(JComponent content) {
- BufferedImage im = new BufferedImage(content.getWidth(), content.getHeight(),
- TYPE_INT_RGB);
- Graphics g = im.getGraphics();
- content.paint(g);
- g.dispose();
- return im;
- }
-}
diff --git a/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java
new file mode 100644
index 00000000000..f9aade1d24d
--- /dev/null
+++ b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java
@@ -0,0 +1,123 @@
+/*
+ * 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 8192888
+ * @key headful
+ * @summary Verifies ProgressBar in Synth L&F renders background
+ * when border is not painted
+ * @run main TestNimbusProgressBarBorder
+ */
+
+import java.io.File;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GridBagLayout;
+import java.awt.image.BufferedImage;
+import java.awt.Rectangle;
+import java.awt.Robot;
+
+import javax.imageio.ImageIO;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.UIManager;
+import javax.swing.SwingUtilities;
+
+public class TestNimbusProgressBarBorder {
+
+ private static JFrame frame;
+ private static JProgressBar progressBar;
+ private static boolean failure = true;
+ private static volatile Rectangle rect;
+
+ public static void main(String[] args) throws Exception {
+ int width = 200;
+ int height = 100;
+ try {
+ Robot robot = new Robot();
+ SwingUtilities.invokeAndWait(() -> {
+ try {
+ // Set Nimbus L&F
+ UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ frame = new JFrame("Nimbus JProgressBar Test");
+ frame.setSize(width, height);
+
+ // ProgressBar setup
+ progressBar = new JProgressBar(0, 100);
+ progressBar.setValue(0);
+ progressBar.setBorderPainted(false);
+
+ JPanel center = new JPanel(new GridBagLayout());
+ center.setBackground(Color.WHITE);
+ center.add(progressBar);
+
+ frame.add(center, BorderLayout.CENTER);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ });
+ robot.waitForIdle();
+ robot.delay(1000);
+ SwingUtilities.invokeAndWait(() -> {
+ rect = progressBar.getBounds();
+ });
+
+ BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2d = (Graphics2D) img.getGraphics();
+ g2d.setColor(Color.WHITE);
+ g2d.fillRect(0, 0, rect.width, rect.height);
+ progressBar.paint(g2d);
+ g2d.dispose();
+
+ robot.waitForIdle();
+ robot.delay(100);
+
+ for (int x = 10; x < (10 + rect.width / 2); x++) {
+ for (int y = 10; y < (10 + rect.height / 2); y++) {
+ Color col = new Color(img.getRGB(x, y));
+ if (!col.equals(Color.WHITE)) {
+ failure = false;
+ break;
+ }
+ }
+ }
+ if (failure) {
+ ImageIO.write(img, "png", new File("ProgressBarTest.png"));
+ throw new RuntimeException("ProgressBar background not drawn");
+ }
+ } finally {
+ SwingUtilities.invokeAndWait(() -> {
+ if (frame != null) {
+ frame.dispose();
+ }
+ });
+ }
+ }
+}
diff --git a/test/jdk/javax/swing/regtesthelpers/Util.java b/test/jdk/javax/swing/regtesthelpers/Util.java
index 5f81384028e..ddbf32f938d 100644
--- a/test/jdk/javax/swing/regtesthelpers/Util.java
+++ b/test/jdk/javax/swing/regtesthelpers/Util.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -21,14 +21,32 @@
* questions.
*/
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.*;
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
+import java.util.function.Predicate;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.SwingUtilities;
+
+import static javax.swing.SwingUtilities.isEventDispatchThread;
/**
*
This class contains utilities useful for regression testing.
@@ -123,26 +141,44 @@ public static void generateOOME() {
}
/**
- * Find a sub component by class name.
- * Always run this method on the EDT thread
+ * Find a subcomponent by class name.
*/
public static Component findSubComponent(Component parent, String className) {
- String parentClassName = parent.getClass().getName();
+ return findComponent((Container) parent,
+ c -> c.getClass()
+ .getName()
+ .contains(className));
+ }
- if (parentClassName.contains(className)) {
- return parent;
+ /**
+ * Find a component based on predicate.
+ */
+ public static Component findComponent(final Container container,
+ final Predicate predicate) {
+ try {
+ if (isEventDispatchThread()) {
+ return findComponentImpl(container, predicate);
+ } else {
+ return Util.invokeOnEDT(() -> findComponentImpl(container, predicate));
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Error occurred while finding component", e);
}
+ }
- if (parent instanceof Container) {
- for (Component child : ((Container) parent).getComponents()) {
- Component subComponent = findSubComponent(child, className);
-
- if (subComponent != null) {
- return subComponent;
+ private static Component findComponentImpl(final Container container,
+ final Predicate