diff --git a/.jcheck/conf b/.jcheck/conf index d89c28169f49..8bd21f7117b3 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=21.0.10 +version=21.0.11 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index be099e50a047..955b8c9ba830 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ ################################################################################ # Minimum supported versions -JTREG_MINIMUM_VERSION=7.3.1 +JTREG_MINIMUM_VERSION=7.4 GTEST_MINIMUM_VERSION=1.14.0 ############################################################################### diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index 00e73f7dd6c5..062e10017012 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -47,7 +47,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/github-actions.conf b/make/conf/github-actions.conf index 0a81e7fcc465..ad1237543df7 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -26,7 +26,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) GTEST_VERSION=1.14.0 -JTREG_VERSION=7.3.1+1 +JTREG_VERSION=7.4+1 LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-21.0.6/sapmachine-jdk-21.0.6_linux-x64_bin.tar.gz diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 7e0bdc3a0cb3..ef331bbbb1bf 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1185,9 +1185,9 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "jpg", product: "jtreg", - version: "7.3.1", + version: "7.4", build_number: "1", - file: "bundles/jtreg-7.3.1+1.zip", + file: "bundles/jtreg-7.4+1.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "home_path") + "/bin", configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"), diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 5bc602fd5c4d..f7d91c667137 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -28,15 +28,15 @@ DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=10 +DEFAULT_VERSION_UPDATE=11 DEFAULT_VERSION_PATCH=0 -DEFAULT_VERSION_EXTRA1=1 +DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2026-02-17 +DEFAULT_VERSION_DATE=2026-04-21 DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="20 21" DEFAULT_JDK_SOURCE_TARGET_VERSION=21 -DEFAULT_PROMOTED_VERSION_PRE= +DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 63c0f284db2d..e2a82106fb5f 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -1268,11 +1268,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(CCR0, R11_scratch1, R14_bcp); beq(CCR0, 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/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index f8f435c3522c..60182fbabd10 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -13073,27 +13073,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); %} @@ -13115,12 +13115,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); %} %} @@ -13238,7 +13238,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); %} %} @@ -13267,7 +13267,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/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index a6e96b76ca30..1186c78b865a 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, 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 @@ -297,6 +297,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, } else { log_debug(os, container)("Can't read %s, %s", controllers_file, os::strerror(errno)); *flags = INVALID_CGROUPS_V2; + fclose(controllers); return false; } for (int i = 0; i < CG_INFO_LENGTH; i++) { @@ -357,7 +358,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, all_required_controllers_enabled = all_required_controllers_enabled && cg_infos[i]._enabled; } if (log_is_enabled(Debug, os, container) && !cg_infos[i]._enabled) { - log_debug(os, container)("controller %s is not enabled\n", cg_controller_name[i]); + log_debug(os, container)("controller %s is not enabled", cg_controller_name[i]); } } } diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 284574c0bb3e..6b32408f801c 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -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; diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 027461befc60..8c8f558116a0 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) { diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index b601ef0264a1..250d0273fc4d 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -98,6 +98,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); diff --git a/src/hotspot/os/linux/gc/x/xSyscall_linux.hpp b/src/hotspot/os/linux/gc/x/xSyscall_linux.hpp index f16d2b2ffdcc..b3be45b49d79 100644 --- a/src/hotspot/os/linux/gc/x/xSyscall_linux.hpp +++ b/src/hotspot/os/linux/gc/x/xSyscall_linux.hpp @@ -35,6 +35,10 @@ #define MPOL_F_ADDR (1<<1) #endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0x100000 +#endif + class XSyscall : public AllStatic { public: static int memfd_create(const char* name, unsigned int flags); diff --git a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp index 1e1becf5a140..e5978c8d93a1 100644 --- a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp +++ b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp @@ -35,6 +35,10 @@ #define MPOL_F_ADDR (1<<1) #endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0x100000 +#endif + class ZSyscall : public AllStatic { public: static int memfd_create(const char* name, unsigned int flags); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 2c04e26673d2..e54b4cc7a1cd 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -3637,8 +3637,23 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { // may not start from the requested address. Unlike Linux mmap(), this // function returns null to indicate failure. static char* anon_mmap(char* requested_addr, size_t bytes) { - // MAP_FIXED is intentionally left out, to leave existing mappings intact. - const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; + // If a requested address was given: + // + // The POSIX-conforming way is to *omit* MAP_FIXED. This will leave existing mappings intact. + // If the requested mapping area is blocked by a pre-existing mapping, the kernel will map + // somewhere else. On Linux, that alternative address appears to have no relation to the + // requested address. + // Unfortunately, this is not what we need - if we requested a specific address, we'd want + // to map there and nowhere else. Therefore we will unmap the block again, which means we + // just executed a needless mmap->munmap cycle. + // Since Linux 4.17, the kernel offers MAP_FIXED_NOREPLACE. With this flag, if a pre- + // existing mapping exists, the kernel will not map at an alternative point but instead + // return an error. We can therefore save that unnecessary mmap-munmap cycle. + // + // Backward compatibility: Older kernels will ignore the unknown flag; so mmap will behave + // as in mode (a). + const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS | + ((requested_addr != nullptr) ? MAP_FIXED_NOREPLACE : 0); // Map reserved/uncommitted pages PROT_NONE so we fail early if we // touch an uncommitted page. Otherwise, the read/write might @@ -4407,6 +4422,7 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool if (addr != nullptr) { // mmap() is successful but it fails to reserve at the requested address + log_trace(os, map)("Kernel rejected " PTR_FORMAT ", offered " PTR_FORMAT ".", p2i(requested_addr), p2i(addr)); anon_munmap(addr, bytes); } diff --git a/src/hotspot/os/posix/gc/x/xVirtualMemory_posix.cpp b/src/hotspot/os/posix/gc/x/xVirtualMemory_posix.cpp index e2422eb0978f..2c15c109d6d3 100644 --- a/src/hotspot/os/posix/gc/x/xVirtualMemory_posix.cpp +++ b/src/hotspot/os/posix/gc/x/xVirtualMemory_posix.cpp @@ -25,6 +25,9 @@ #include "gc/x/xAddress.inline.hpp" #include "gc/x/xVirtualMemory.hpp" #include "logging/log.hpp" +#ifdef LINUX +#include "gc/x/xSyscall_linux.hpp" +#endif #include #include @@ -38,7 +41,9 @@ void XVirtualMemoryManager::pd_initialize_after_reserve() { } bool XVirtualMemoryManager::pd_reserve(uintptr_t addr, size_t size) { - const uintptr_t res = (uintptr_t)mmap((void*)addr, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + const int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE LINUX_ONLY(|MAP_FIXED_NOREPLACE); + + const uintptr_t res = (uintptr_t)mmap((void*)addr, size, PROT_NONE, flags, -1, 0); if (res == (uintptr_t)MAP_FAILED) { // Failed to reserve memory return false; diff --git a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp b/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp index 936e734e8ff0..dc577bee59fa 100644 --- a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp +++ b/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp @@ -25,6 +25,9 @@ #include "gc/z/zAddress.inline.hpp" #include "gc/z/zVirtualMemory.hpp" #include "logging/log.hpp" +#ifdef LINUX +#include "gc/z/zSyscall_linux.hpp" +#endif #include #include @@ -38,7 +41,9 @@ void ZVirtualMemoryManager::pd_initialize_after_reserve() { } bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) { - void* const res = mmap((void*)untype(addr), size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + const int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE LINUX_ONLY(|MAP_FIXED_NOREPLACE); + + void* const res = mmap((void*)untype(addr), size, PROT_NONE, flags, -1, 0); if (res == MAP_FAILED) { // Failed to reserve memory return false; diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp index dcc8deebc12f..46f2e4f744eb 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Microsoft Corporation. All rights reserved. - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 263efbeec6bb..aabac6920974 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -1046,7 +1046,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { // longs and doubles will be split into two words. unitsize = sizeof(narrowOop); } - os::print_hex_dump(&lsh, base, top, unitsize, 32, requested_base); + os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base); } } diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp index cf598df59d7a..b71fb7547e54 100644 --- a/src/hotspot/share/classfile/resolutionErrors.cpp +++ b/src/hotspot/share/classfile/resolutionErrors.cpp @@ -74,7 +74,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 @@ -86,7 +86,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 @@ -127,6 +127,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 a80348e506b1..1618da02cb9a 100644 --- a/src/hotspot/share/classfile/resolutionErrors.hpp +++ b/src/hotspot/share/classfile/resolutionErrors.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, 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 @@ -93,10 +93,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 de4efebb2785..5a16d061d648 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" @@ -1829,18 +1830,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 9f65cb593d39..d8b6b933e349 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -282,7 +282,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); protected: diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index 40d63419e7ce..aaef672e6c03 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -672,6 +672,7 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const nm->print_nmethod(true); } else { nm->print(st); + nm->print_code_snippet(st, addr); } return; } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 3808ee26988a..2090d2eed4fd 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -3385,6 +3385,46 @@ void nmethod::print_value_on(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 03b8210c31c8..5fd112c61f8d 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -623,6 +623,7 @@ class nmethod : public CompiledMethod { void print() const; void print(outputStream* st) const; void print_code(); + void print_code_snippet(outputStream* st, address addr) const; #if defined(SUPPORT_DATA_STRUCTS) // print output in opt build for disassembler library diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index 28f850938c46..d4eb6f345b3c 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -69,6 +69,9 @@ void G1Arguments::initialize_alignments() { } size_t G1Arguments::conservative_max_heap_alignment() { + if (FLAG_IS_DEFAULT(G1HeapRegionSize)) { + return HeapRegion::max_ergonomics_size(); + } return HeapRegion::max_region_size(); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index a43e45c4afa8..80d6493963fa 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -386,22 +386,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(). @@ -430,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; } // If the GCLocker is active and we are bound for a GC, try expanding young gen. @@ -631,7 +637,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"); @@ -643,7 +650,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(); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 6afaeb6e6d4a..bd521c347bf7 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -423,18 +423,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, @@ -448,12 +444,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/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index a34d6b854587..2dd6d022df05 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -57,6 +57,10 @@ size_t HeapRegion::max_region_size() { return HeapRegionBounds::max_size(); } +size_t HeapRegion::max_ergonomics_size() { + return HeapRegionBounds::max_ergonomics_size(); +} + size_t HeapRegion::min_region_size_in_words() { return HeapRegionBounds::min_size() >> LogHeapWordSize; } diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 195b7e9d911e..ef1f68d890fb 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -321,6 +321,7 @@ class HeapRegion : public CHeapObj { } static size_t max_region_size(); + static size_t max_ergonomics_size(); static size_t min_region_size_in_words(); // It sets up the heap region size (GrainBytes / GrainWords), as well as diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp index cffda333b133..9ce3d0f91646 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupStat.cpp @@ -101,13 +101,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)); } @@ -218,14 +222,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/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 13500f507180..375c7dca456f 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -290,12 +290,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 @@ -334,10 +333,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 { diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 43a40a60e08e..282e19e81beb 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1342,8 +1342,10 @@ 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/compile.cpp b/src/hotspot/share/opto/compile.cpp index cbe7b929c8d8..b83464783d12 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -833,18 +833,8 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, if (failing()) return; NOT_PRODUCT( verify_graph_edges(); ) - // If any phase is randomized for stress testing, seed random number - // generation and log the seed for repeatability. if (StressLCM || StressGCM || StressIGVN || StressCCP || StressIncrementalInlining) { - if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { - _stress_seed = static_cast(Ticks::now().nanoseconds()); - FLAG_SET_ERGO(StressSeed, _stress_seed); - } else { - _stress_seed = StressSeed; - } - if (_log != nullptr) { - _log->elem("stress_test seed='%u'", _stress_seed); - } + initialize_stress_seed(directive); } // Now optimize @@ -965,6 +955,11 @@ Compile::Compile( ciEnv* ci_env, _igvn_worklist = new (comp_arena()) Unique_Node_List(comp_arena()); _types = new (comp_arena()) Type_Array(comp_arena()); _node_hash = new (comp_arena()) NodeHash(comp_arena(), 255); + + if (StressLCM || StressGCM) { + initialize_stress_seed(directive); + } + { PhaseGVN gvn; set_initial_gvn(&gvn); // not significant, but GraphKit guys use it pervasively @@ -5011,6 +5006,18 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) { // Auxiliary methods to support randomized stressing/fuzzing. +void Compile::initialize_stress_seed(const DirectiveSet* directive) { + if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { + _stress_seed = static_cast(Ticks::now().nanoseconds()); + FLAG_SET_ERGO(StressSeed, _stress_seed); + } else { + _stress_seed = StressSeed; + } + if (_log != nullptr) { + _log->elem("stress_test seed='%u'", _stress_seed); + } +} + int Compile::random() { _stress_seed = os::next_random(_stress_seed); return static_cast(_stress_seed); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 0c8df77cce28..b1a63a28bceb 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1232,6 +1232,9 @@ class Compile : public Phase { int random(); bool randomized_select(int count); + // seed random number generation and log the seed for repeatability. + void initialize_stress_seed(const DirectiveSet* directive); + // supporting clone_map CloneMap& clone_map(); void set_clone_map(Dict* d); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index dc0cff5faf17..fd44971fe63b 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -930,56 +930,73 @@ bool os::print_function_and_library_name(outputStream* st, return have_function_name || have_library_name; } -ATTRIBUTE_NO_ASAN static bool read_safely_from(intptr_t* p, intptr_t* result) { - const intptr_t errval = 0x1717; - intptr_t i = SafeFetchN(p, errval); +ATTRIBUTE_NO_ASAN static bool read_safely_from(const uintptr_t* p, uintptr_t* result) { + DEBUG_ONLY(*result = 0xAAAA;) + const uintptr_t errval = 0x1717; + uintptr_t i = (uintptr_t)SafeFetchN((intptr_t*)p, errval); if (i == errval) { - i = SafeFetchN(p, ~errval); + i = (uintptr_t)SafeFetchN((intptr_t*)p, ~errval); if (i == ~errval) { return false; } } - (*result) = i; + (*result) = (uintptr_t)i; return true; } -static void print_hex_location(outputStream* st, address p, int unitsize) { +// Helper for os::print_hex_dump +static void print_ascii_form(stringStream& ascii_form, uint64_t value, int unitsize) { + union { + uint64_t v; + uint8_t c[sizeof(v)]; + } u = { value }; + for (int i = 0; i < unitsize; i++) { + const int idx = LITTLE_ENDIAN_ONLY(i) BIG_ENDIAN_ONLY(sizeof(u.v) - unitsize + i); + const uint8_t c = u.c[idx]; + ascii_form.put(isprint(c) && isascii(c) ? c : '.'); + } +} + +// Helper for os::print_hex_dump +static void print_hex_location(outputStream* st, const_address p, int unitsize, stringStream& ascii_form) { assert(is_aligned(p, unitsize), "Unaligned"); - address pa = align_down(p, sizeof(intptr_t)); + const uintptr_t* pa = (const uintptr_t*) align_down(p, sizeof(intptr_t)); #ifndef _LP64 // Special handling for printing qwords on 32-bit platforms if (unitsize == 8) { - intptr_t i1, i2; - if (read_safely_from((intptr_t*)pa, &i1) && - read_safely_from((intptr_t*)pa + 1, &i2)) { + uintptr_t i1 = 0, i2 = 0; + if (read_safely_from(pa, &i1) && + read_safely_from(pa + 1, &i2)) { const uint64_t value = LITTLE_ENDIAN_ONLY((((uint64_t)i2) << 32) | i1) BIG_ENDIAN_ONLY((((uint64_t)i1) << 32) | i2); st->print("%016" FORMAT64_MODIFIER "x", value); + print_ascii_form(ascii_form, value, unitsize); } else { st->print_raw("????????????????"); } return; } #endif // 32-bit, qwords - intptr_t i = 0; - if (read_safely_from((intptr_t*)pa, &i)) { + uintptr_t i = 0; + if (read_safely_from(pa, &i)) { // bytes: CA FE BA BE DE AD C0 DE // bytoff: 0 1 2 3 4 5 6 7 // LE bits: 0 8 16 24 32 40 48 56 // BE bits: 56 48 40 32 24 16 8 0 - const int offset = (int)(p - (address)pa); + const int offset = (int)(p - (const_address)pa); const int bitoffset = LITTLE_ENDIAN_ONLY(offset * BitsPerByte) BIG_ENDIAN_ONLY((int)((sizeof(intptr_t) - unitsize - offset) * BitsPerByte)); const int bitfieldsize = unitsize * BitsPerByte; - intptr_t value = bitfield(i, bitoffset, bitfieldsize); + uintptr_t value = bitfield(i, bitoffset, bitfieldsize); switch (unitsize) { case 1: st->print("%02x", (u1)value); break; case 2: st->print("%04x", (u2)value); break; case 4: st->print("%08x", (u4)value); break; case 8: st->print("%016" FORMAT64_MODIFIER "x", (u8)value); break; } + print_ascii_form(ascii_form, value, unitsize); } else { switch (unitsize) { case 1: st->print_raw("??"); break; @@ -990,36 +1007,56 @@ static void print_hex_location(outputStream* st, address p, int unitsize) { } } -void os::print_hex_dump(outputStream* st, address start, address end, int unitsize, - int bytes_per_line, address logical_start) { +void os::print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, + bool print_ascii, int bytes_per_line, const_address logical_start) { + constexpr int max_bytes_per_line = 64; assert(unitsize == 1 || unitsize == 2 || unitsize == 4 || unitsize == 8, "just checking"); + assert(bytes_per_line > 0 && bytes_per_line <= max_bytes_per_line && + is_power_of_2(bytes_per_line), "invalid bytes_per_line"); start = align_down(start, unitsize); logical_start = align_down(logical_start, unitsize); bytes_per_line = align_up(bytes_per_line, 8); int cols = 0; - int cols_per_line = bytes_per_line / unitsize; + const int cols_per_line = bytes_per_line / unitsize; - address p = start; - address logical_p = logical_start; + const_address p = start; + const_address logical_p = logical_start; + + stringStream ascii_form; // Print out the addresses as if we were starting from logical_start. - st->print(PTR_FORMAT ": ", p2i(logical_p)); while (p < end) { - print_hex_location(st, p, unitsize); + if (cols == 0) { + st->print(PTR_FORMAT ": ", p2i(logical_p)); + } + print_hex_location(st, p, unitsize, ascii_form); p += unitsize; logical_p += unitsize; cols++; - if (cols >= cols_per_line && p < end) { - cols = 0; + if (cols >= cols_per_line) { + if (print_ascii && !ascii_form.is_empty()) { + st->print(" %s", ascii_form.base()); + } + ascii_form.reset(); st->cr(); - st->print(PTR_FORMAT ": ", p2i(logical_p)); + cols = 0; } else { st->print(" "); } } - st->cr(); + + if (cols > 0) { // did not print a full line + if (print_ascii) { + // indent last ascii part to match that of full lines + const int size_of_printed_unit = unitsize * 2; + const int space_left = (cols_per_line - cols) * (size_of_printed_unit + 1); + st->sp(space_left); + st->print(" %s", ascii_form.base()); + } + st->cr(); + } } void os::print_dhm(outputStream* st, const char* startStr, long sec) { @@ -1057,7 +1094,7 @@ void os::print_tos(outputStream* st, address sp) { void os::print_instructions(outputStream* st, address pc, int unitsize) { st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 256, pc + 256, unitsize); + print_hex_dump(st, pc - 256, pc + 256, unitsize, /* print_ascii=*/false); } void os::print_environment_variables(outputStream* st, const char** env_list) { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 8e1c430c650e..13629829d9e2 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -842,10 +842,10 @@ class os: AllStatic { // return current frame. pc() and sp() are set to null on failure. static frame current_frame(); - static void print_hex_dump(outputStream* st, address start, address end, int unitsize, - int bytes_per_line, address logical_start); - static void print_hex_dump(outputStream* st, address start, address end, int unitsize) { - print_hex_dump(st, start, end, unitsize, /*bytes_per_line=*/16, /*logical_start=*/start); + static void print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, bool print_ascii, + int bytes_per_line, const_address logical_start); + static void print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, bool print_ascii = true) { + print_hex_dump(st, start, end, unitsize, print_ascii, /*bytes_per_line=*/16, /*logical_start=*/start); } // returns a string to describe the exception/signal; diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 625fdcc414fe..9d4cae2a08d4 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -473,6 +473,8 @@ inline address_word mask_address_bits(address x, int m) { return address_w inline address_word castable_address(address x) { return address_word(x) ; } inline address_word castable_address(void* x) { return address_word(x) ; } +typedef const u_char* const_address; + // Pointer subtraction. // The idea here is to avoid ptrdiff_t, which is signed and so doesn't have // the range we might need to find differences from one end of the heap diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index eaef66f7186c..5e513eb2ba13 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -226,6 +226,7 @@ class stringStream : public outputStream { return _buffer; }; void reset(); + bool is_empty() const { return _buffer[0] == '\0'; } // Copy to a resource, or C-heap, array as requested char* as_string(bool c_heap = false) const; }; 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 000000000000..c0fd9ffa599e --- /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 10093137151d..6a4e28372e50 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 @@ -147,6 +147,12 @@ public Void run() { 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" @@ -158,9 +164,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/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index e472ba945501..facd207bec3d 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, 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 @@ -356,8 +356,12 @@ public void setLength(int newLength) { */ @Override public char charAt(int index) { + byte coder = this.coder; + byte[] value = this.value; + // Ensure count is less than or equal to capacity (racy reads and writes can produce inconsistent values) + int count = Math.min(this.count, value.length >> coder); checkIndex(index, count); - if (isLatin1()) { + if (coder == LATIN1) { return (char)(value[index] & 0xff); } return StringUTF16.getChar(value, index); @@ -416,6 +420,7 @@ public int codePointAt(int index) { * of this sequence. */ public int codePointBefore(int index) { + byte[] value = this.value; int i = index - 1; checkIndex(i, count); if (isLatin1()) { @@ -1720,7 +1725,7 @@ private final void putCharsAt(int index, CharSequence s, int off, int end) { } else { inflate(); // store c to make sure it has a UTF16 char - StringUTF16.putChar(this.value, j++, c); + StringUTF16.putCharSB(this.value, j++, c); i++; StringUTF16.putCharsSB(this.value, j, s, i, end); return; @@ -1810,7 +1815,7 @@ private final void appendChars(CharSequence s, int off, int end) { count = j; inflate(); // Store c to make sure sb has a UTF16 char - StringUTF16.putChar(this.value, j++, c); + StringUTF16.putCharSB(this.value, j++, c); count = j; i++; StringUTF16.putCharsSB(this.value, j, s, i, end); diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java index 01edb885726c..03f618dd7d2c 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 @@ -839,12 +840,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. + *
  • + *
* * @param type the type of keystore. * See the KeyStore section in the Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * 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. + * * @param type the type of keystore. * See the KeyStore section in the @@ -913,8 +936,15 @@ public static KeyStore getInstance(String type, String provider) throws KeyStoreException, NoSuchProviderException { Objects.requireNonNull(type, "null type name"); - if (provider == null || provider.isEmpty()) + + if (provider == null || provider.isEmpty()) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("KEYSTORE", type)) { + throw new KeyStoreException(type + " is disabled"); + } + try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); @@ -931,6 +961,14 @@ public static KeyStore getInstance(String type, String provider) * object is returned. Note that the specified provider object * does not have to be registered in the provider list. * + * @implNote + * The JDK Reference Implementation additionally uses + * 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. + * * @param type the type of keystore. * See the KeyStore section in the @@ -958,8 +996,15 @@ public static KeyStore getInstance(String type, Provider provider) throws KeyStoreException { Objects.requireNonNull(type, "null type name"); - if (provider == null) + + if (provider == null) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("KEYSTORE", type)) { + throw new KeyStoreException(type + " is disabled"); + } + try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); @@ -1675,6 +1720,14 @@ public final void setEntry(String alias, Entry entry, *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * 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. Disallowed type will be skipped. + * * @param file the keystore file * @param password the keystore password, which may be {@code null} * @@ -1731,6 +1784,14 @@ public static final KeyStore getInstance(File file, char[] password) *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * 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. Disallowed type will be skipped. + * * @param file the keystore file * @param param the {@code LoadStoreParameter} that specifies how to load * the keystore, which may be {@code null} @@ -1802,8 +1863,12 @@ private static final KeyStore getInstance(File file, char[] password, kdebug.println(s.getAlgorithm() + " keystore detected: " + file); } - keystore = new KeyStore(impl, p, s.getAlgorithm()); - break; + String ksAlgo = s.getAlgorithm(); + if (CryptoAlgorithmConstraints.permits( + "KEYSTORE", ksAlgo)) { + keystore = new KeyStore(impl, p, ksAlgo); + break; + } } } catch (NoSuchAlgorithmException e) { // ignore diff --git a/src/java.base/share/classes/java/security/MessageDigest.java b/src/java.base/share/classes/java/security/MessageDigest.java index 36c92df556e0..6a95fbdec14e 100644 --- a/src/java.base/share/classes/java/security/MessageDigest.java +++ b/src/java.base/share/classes/java/security/MessageDigest.java @@ -33,6 +33,7 @@ import sun.security.jca.GetInstance; import sun.security.util.Debug; import sun.security.util.MessageDigestSpi2; +import sun.security.util.CryptoAlgorithmConstraints; import javax.crypto.SecretKey; @@ -152,12 +153,22 @@ private MessageDigest(String algorithm, Provider p) { * 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 following + * security properties: + *

    + *
  • the {@code jdk.security.provider.preferred} * {@link Security#getProperty(String) Security} property to determine * the preferred provider order for the specified algorithm. 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 algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + *
  • + *
* * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the
Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the @@ -241,12 +264,18 @@ public static MessageDigest getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (provider == null || provider.isEmpty()) + + if (provider == null || provider.isEmpty()) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("MessageDigest", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); + } - MessageDigest md; GetInstance.Instance instance = GetInstance.getInstance("MessageDigest", MessageDigestSpi.class, algorithm, provider); + MessageDigest md; if (instance.impl instanceof MessageDigest messageDigest) { md = messageDigest; md.provider = instance.provider; @@ -266,6 +295,14 @@ public static MessageDigest getInstance(String algorithm, String provider) * is returned. Note that the specified provider does not * have to be registered in the provider list. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the @@ -295,8 +332,15 @@ public static MessageDigest getInstance(String algorithm, throws NoSuchAlgorithmException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (provider == null) + + if (provider == null) { throw new IllegalArgumentException("missing provider"); + } + + if (!CryptoAlgorithmConstraints.permits("MessageDigest", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); + } + Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); if (objs[0] instanceof MessageDigest md) { md.provider = (Provider)objs[1]; diff --git a/src/java.base/share/classes/java/security/Signature.java b/src/java.base/share/classes/java/security/Signature.java index 769a9ce813bf..835f7d43f92a 100644 --- a/src/java.base/share/classes/java/security/Signature.java +++ b/src/java.base/share/classes/java/security/Signature.java @@ -36,14 +36,12 @@ import java.security.Provider.Service; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.BadPaddingException; -import javax.crypto.NoSuchPaddingException; import jdk.internal.access.JavaSecuritySignatureAccess; import jdk.internal.access.SharedSecrets; import sun.security.util.Debug; +import sun.security.util.CryptoAlgorithmConstraints; + import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; import sun.security.util.KnownOIDs; @@ -203,20 +201,6 @@ protected Signature(String algorithm) { this.algorithm = algorithm; } - // name of the special signature alg - private static final String RSA_SIGNATURE = "NONEwithRSA"; - - // name of the equivalent cipher alg - private static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; - - // all the services we need to lookup for compatibility with Cipher - private static final List rsaIds = List.of( - new ServiceId("Signature", "NONEwithRSA"), - new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), - new ServiceId("Cipher", "RSA/ECB"), - new ServiceId("Cipher", "RSA//PKCS1Padding"), - new ServiceId("Cipher", "RSA")); - /** * Returns a {@code Signature} object that implements the specified * signature algorithm. @@ -231,12 +215,22 @@ protected Signature(String algorithm) { * 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 following + * security properties: + *
    + *
  • the {@code jdk.security.provider.preferred} * {@link Security#getProperty(String) Security} property to determine * the preferred provider order for the specified algorithm. 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 algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + *
  • + *
* * @param algorithm the standard name of the algorithm requested. * See the Signature section in the
list; - if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { - list = GetInstance.getServices(rsaIds); - } else { - list = GetInstance.getServices("Signature", algorithm); + + if (!CryptoAlgorithmConstraints.permits("Signature", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); } + + List list = GetInstance.getServices("Signature", algorithm); Iterator t = list.iterator(); if (!t.hasNext()) { throw new NoSuchAlgorithmException @@ -319,10 +313,6 @@ private static Signature getInstance(Instance instance, String algorithm) { } private static boolean isSpi(Service s) { - if (s.getType().equals("Cipher")) { - // must be a CipherSpi, which we can wrap with the CipherAdapter - return true; - } String className = s.getClassName(); Boolean result = signatureInfo.get(className); if (result == null) { @@ -360,6 +350,14 @@ private static boolean isSpi(Service s) { *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the Signature section in the @@ -387,18 +385,11 @@ private static boolean isSpi(Service s) { public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { - // exception compatibility with existing code - if (provider == null || provider.isEmpty()) { - throw new IllegalArgumentException("missing provider"); - } - Provider p = Security.getProvider(provider); - if (p == null) { - throw new NoSuchProviderException - ("no such provider: " + provider); - } - return getInstanceRSA(p); + + if (!CryptoAlgorithmConstraints.permits("Signature", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); } + Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); @@ -413,6 +404,14 @@ public static Signature getInstance(String algorithm, String provider) * is returned. Note that the specified provider does not * have to be registered in the provider list. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param algorithm the name of the algorithm requested. * See the Signature section in the @@ -438,40 +437,16 @@ public static Signature getInstance(String algorithm, String provider) public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Objects.requireNonNull(algorithm, "null algorithm name"); - if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { - // exception compatibility with existing code - if (provider == null) { - throw new IllegalArgumentException("missing provider"); - } - return getInstanceRSA(provider); + + if (!CryptoAlgorithmConstraints.permits("Signature", algorithm)) { + throw new NoSuchAlgorithmException(algorithm + " is disabled"); } + Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } - // return an implementation for NONEwithRSA, which is a special case - // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper - private static Signature getInstanceRSA(Provider p) - throws NoSuchAlgorithmException { - // try Signature first - Service s = p.getService("Signature", RSA_SIGNATURE); - if (s != null) { - Instance instance = GetInstance.getInstance(s, SignatureSpi.class); - return getInstance(instance, RSA_SIGNATURE); - } - // check Cipher - try { - Cipher c = Cipher.getInstance(RSA_CIPHER, p); - return Delegate.of(new CipherAdapter(c), RSA_SIGNATURE); - } catch (GeneralSecurityException e) { - // throw Signature style exception message to avoid confusion, - // but append Cipher exception as cause - throw new NoSuchAlgorithmException("no such algorithm: " - + RSA_SIGNATURE + " for provider " + p.getName(), e); - } - } - /** * Returns the provider of this {@code Signature} object. * @@ -1167,22 +1142,12 @@ public Object clone() throws CloneNotSupportedException { private static SignatureSpi newInstance(Service s) throws NoSuchAlgorithmException { - if (s.getType().equals("Cipher")) { - // must be NONEwithRSA - try { - Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider()); - return new CipherAdapter(c); - } catch (NoSuchPaddingException e) { - throw new NoSuchAlgorithmException(e); - } - } else { - Object o = s.newInstance(null); - if (!(o instanceof SignatureSpi)) { - throw new NoSuchAlgorithmException - ("Not a SignatureSpi: " + o.getClass().getName()); - } - return (SignatureSpi)o; + Object o = s.newInstance(null); + if (!(o instanceof SignatureSpi)) { + throw new NoSuchAlgorithmException + ("Not a SignatureSpi: " + o.getClass().getName()); } + return (SignatureSpi)o; } // max number of debug warnings to print from chooseFirstProvider() @@ -1459,92 +1424,4 @@ protected AlgorithmParameters engineGetParameters() { return sigSpi.engineGetParameters(); } } - - // adapter for RSA/ECB/PKCS1Padding ciphers - @SuppressWarnings("deprecation") - private static class CipherAdapter extends SignatureSpi { - - private final Cipher cipher; - - private ByteArrayOutputStream data; - - CipherAdapter(Cipher cipher) { - this.cipher = cipher; - } - - protected void engineInitVerify(PublicKey publicKey) - throws InvalidKeyException { - cipher.init(Cipher.DECRYPT_MODE, publicKey); - if (data == null) { - data = new ByteArrayOutputStream(128); - } else { - data.reset(); - } - } - - protected void engineInitSign(PrivateKey privateKey) - throws InvalidKeyException { - cipher.init(Cipher.ENCRYPT_MODE, privateKey); - data = null; - } - - protected void engineInitSign(PrivateKey privateKey, - SecureRandom random) throws InvalidKeyException { - cipher.init(Cipher.ENCRYPT_MODE, privateKey, random); - data = null; - } - - protected void engineUpdate(byte b) throws SignatureException { - engineUpdate(new byte[] {b}, 0, 1); - } - - protected void engineUpdate(byte[] b, int off, int len) - throws SignatureException { - if (data != null) { - data.write(b, off, len); - return; - } - byte[] out = cipher.update(b, off, len); - if ((out != null) && (out.length != 0)) { - throw new SignatureException - ("Cipher unexpectedly returned data"); - } - } - - protected byte[] engineSign() throws SignatureException { - try { - return cipher.doFinal(); - } catch (IllegalBlockSizeException | BadPaddingException e) { - throw new SignatureException("doFinal() failed", e); - } - } - - protected boolean engineVerify(byte[] sigBytes) - throws SignatureException { - try { - byte[] out = cipher.doFinal(sigBytes); - byte[] dataBytes = data.toByteArray(); - data.reset(); - return MessageDigest.isEqual(out, dataBytes); - } 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); - } - } - - protected void engineSetParameter(String param, Object value) - throws InvalidParameterException { - throw new InvalidParameterException("Parameters not supported"); - } - - protected Object engineGetParameter(String param) - throws InvalidParameterException { - throw new InvalidParameterException("Parameters not supported"); - } - - } - } diff --git a/src/java.base/share/classes/java/time/ZoneOffset.java b/src/java.base/share/classes/java/time/ZoneOffset.java index 14ac5fcfb6ba..520a0e0b9a19 100644 --- a/src/java.base/share/classes/java/time/ZoneOffset.java +++ b/src/java.base/share/classes/java/time/ZoneOffset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -424,11 +424,17 @@ public static ZoneOffset ofTotalSeconds(int totalSeconds) { throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00"); } if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) { - return SECONDS_CACHE.computeIfAbsent(totalSeconds, totalSecs -> { - ZoneOffset result = new ZoneOffset(totalSecs); + Integer totalSecs = totalSeconds; + ZoneOffset result = SECONDS_CACHE.get(totalSecs); + if (result == null) { + result = new ZoneOffset(totalSeconds); + var existing = SECONDS_CACHE.putIfAbsent(totalSecs, result); + if (existing != null) { + result = existing; + } ID_CACHE.putIfAbsent(result.getId(), result); - return result; - }); + } + return result; } else { return new ZoneOffset(totalSeconds); } diff --git a/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java b/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java index 5ee4c5c23c81..5be33551c707 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java +++ b/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, 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 @@ -309,7 +309,15 @@ public Iterator> getTextIterator(Chronology chrono, Temporal private Object findStore(TemporalField field, Locale locale) { Entry key = createEntry(field, locale); - return CACHE.computeIfAbsent(key, e -> createStore(e.getKey(), e.getValue())); + Object store = CACHE.get(key); + if (store == null) { + store = createStore(field, locale); + var existing = CACHE.putIfAbsent(key, store); + if (existing != null) { + store = existing; + } + } + return store; } private static int toWeekDay(int calWeekDay) { diff --git a/src/java.base/share/classes/java/time/format/DecimalStyle.java b/src/java.base/share/classes/java/time/format/DecimalStyle.java index b2513888790e..a9ad8a4e273e 100644 --- a/src/java.base/share/classes/java/time/format/DecimalStyle.java +++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, 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 @@ -160,7 +160,15 @@ public static DecimalStyle ofDefaultLocale() { */ public static DecimalStyle of(Locale locale) { Objects.requireNonNull(locale, "locale"); - return CACHE.computeIfAbsent(locale, DecimalStyle::create); + DecimalStyle info = CACHE.get(locale); + if (info == null) { + info = create(locale); + var existing = CACHE.putIfAbsent(locale, info); + if (existing != null) { + info = existing; + } + } + return info; } private static DecimalStyle create(Locale locale) { diff --git a/src/java.base/share/classes/javax/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java index 3e692b37b79e..bef5079cb440 100644 --- a/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/src/java.base/share/classes/javax/crypto/Cipher.java @@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.regex.*; - import java.security.*; import java.security.Provider.Service; import java.security.spec.AlgorithmParameterSpec; @@ -46,6 +45,7 @@ import sun.security.util.Debug; import sun.security.jca.*; import sun.security.util.KnownOIDs; +import sun.security.util.CryptoAlgorithmConstraints; /** * This class provides the functionality of a cryptographic cipher for @@ -310,19 +310,23 @@ private Cipher(CipherSpi firstSpi, Service firstService, private static final String SHA512TRUNCATED = "SHA512/2"; + // Parse the specified cipher transformation for algorithm and the + // optional mode and padding. If the transformation contains only + // algorithm, then only algorithm is returned. Otherwise, the + // transformation must contain all 3 and they must be non-empty. private static String[] tokenizeTransformation(String transformation) throws NoSuchAlgorithmException { if (transformation == null) { throw new NoSuchAlgorithmException("No transformation given"); } + /* - * array containing the components of a cipher transformation: + * Components of a cipher transformation: * - * index 0: algorithm component (e.g., AES) - * index 1: feedback component (e.g., CFB) - * index 2: padding component (e.g., PKCS5Padding) + * 1) algorithm component (e.g., AES) + * 2) feedback component (e.g., CFB) - optional + * 3) padding component (e.g., PKCS5Padding) - optional */ - String[] parts = { "", "", "" }; // check if the transformation contains algorithms with "/" in their // name which can cause the parsing logic to go wrong @@ -331,27 +335,35 @@ private static String[] tokenizeTransformation(String transformation) int startIdx = (sha512Idx == -1 ? 0 : sha512Idx + SHA512TRUNCATED.length()); int endIdx = transformation.indexOf('/', startIdx); - if (endIdx == -1) { - // algorithm - parts[0] = transformation.trim(); + + boolean algorithmOnly = (endIdx == -1); + String algo = (algorithmOnly ? transformation.trim() : + transformation.substring(0, endIdx).trim()); + if (algo.isEmpty()) { + throw new NoSuchAlgorithmException("Invalid transformation: " + + "algorithm not specified-" + + transformation); + } + if (algorithmOnly) { // done + return new String[] { algo }; } else { - // algorithm/mode/padding - parts[0] = transformation.substring(0, endIdx).trim(); + // continue parsing mode and padding startIdx = endIdx+1; endIdx = transformation.indexOf('/', startIdx); if (endIdx == -1) { throw new NoSuchAlgorithmException("Invalid transformation" + " format:" + transformation); } - parts[1] = transformation.substring(startIdx, endIdx).trim(); - parts[2] = transformation.substring(endIdx+1).trim(); - } - if (parts[0].isEmpty()) { - throw new NoSuchAlgorithmException("Invalid transformation: " + - "algorithm not specified-" + String mode = transformation.substring(startIdx, endIdx).trim(); + String padding = transformation.substring(endIdx+1).trim(); + // ensure mode and padding are specified + if (mode.isEmpty() || padding.isEmpty()) { + throw new NoSuchAlgorithmException("Invalid transformation: " + + "missing mode and/or padding-" + transformation); + } + return new String[] { algo, mode, padding }; } - return parts; } // Provider attribute name for supported chaining mode @@ -447,22 +459,17 @@ private static List getTransforms(String transformation) throws NoSuchAlgorithmException { String[] parts = tokenizeTransformation(transformation); - String alg = parts[0]; - String mode = parts[1]; - String pad = parts[2]; - - if ((mode.length() == 0) && (pad.length() == 0)) { + if (parts.length == 1) { // Algorithm only - Transform tr = new Transform(alg, "", null, null); - return Collections.singletonList(tr); + return List.of(new Transform(parts[0], "", null, null)); } else { - // Algorithm w/ at least mode or padding or both - List list = new ArrayList<>(4); - list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); - list.add(new Transform(alg, "/" + mode, null, pad)); - list.add(new Transform(alg, "//" + pad, mode, null)); - list.add(new Transform(alg, "", mode, pad)); - return list; + // Algorithm w/ both mode and padding + return List.of( + new Transform(parts[0], "/" + parts[1] + "/" + parts[2], + null, null), + new Transform(parts[0], "/" + parts[1], null, parts[2]), + new Transform(parts[0], "//" + parts[2], parts[1], null), + new Transform(parts[0], "", parts[1], parts[2])); } } @@ -498,8 +505,10 @@ private static Transform getTransform(Service s, * requirements of your application. * * @implNote - * The JDK Reference Implementation additionally uses the - * {@code jdk.security.provider.preferred} + * The JDK Reference Implementation additionally uses the following + * security properties: + *

* * @param transformation the name of the transformation, e.g., * AES/CBC/PKCS5Padding. @@ -534,6 +551,13 @@ public static final Cipher getInstance(String transformation) if ((transformation == null) || transformation.isEmpty()) { throw new NoSuchAlgorithmException("Null or empty transformation"); } + + // throws NoSuchAlgorithmException if java.security disables it + if (!CryptoAlgorithmConstraints.permits("Cipher", transformation)) { + throw new NoSuchAlgorithmException(transformation + + " is disabled"); + } + List transforms = getTransforms(transformation); List cipherServices = new ArrayList<>(transforms.size()); for (Transform transform : transforms) { @@ -598,6 +622,14 @@ public static final Cipher getInstance(String transformation) * security_guide_jdk_providers JDK Providers} document for information * on the transformation defaults used by JDK providers. * + * @implNote + * The JDK Reference Implementation additionally uses + * the {@code jdk.crypto.disabledAlgorithms} + * {@link Security#getProperty(String) Security} property to determine + * if the specified algorithm is allowed. If the + * {@systemProperty jdk.crypto.disabledAlgorithms} is set, it supersedes + * the security property value. + * * @param transformation the name of the transformation, * e.g., AES/CBC/PKCS5Padding. * See the Cipher section in the AES/CBC/PKCS5Padding. * See the Cipher section in the transforms = getTransforms(transformation); boolean providerChecked = false; diff --git a/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java b/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java index a1438bcc2062..6bac9c3ede78 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java +++ b/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java @@ -46,7 +46,7 @@ class DirectMethodHandleAccessor extends MethodAccessorImpl { * Creates a MethodAccessorImpl for a non-native method. */ static MethodAccessorImpl methodAccessor(Method method, MethodHandle target) { - assert !Modifier.isNative(method.getModifiers()); + assert !MethodHandleAccessorFactory.isSignaturePolymorphicMethod(method); return new DirectMethodHandleAccessor(method, target, false); } diff --git a/src/java.base/share/classes/jdk/internal/reflect/MethodHandleAccessorFactory.java b/src/java.base/share/classes/jdk/internal/reflect/MethodHandleAccessorFactory.java index 20ddd16d35a6..fa5a115a33ee 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/MethodHandleAccessorFactory.java +++ b/src/java.base/share/classes/jdk/internal/reflect/MethodHandleAccessorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; @@ -169,7 +170,7 @@ static FieldAccessorImpl newFieldAccessor(Field field, boolean isReadOnly) { } private static MethodHandle getDirectMethod(Method method, boolean callerSensitive) throws IllegalAccessException { - var mtype = methodType(method.getReturnType(), method.getParameterTypes()); + var mtype = methodType(method.getReturnType(), reflectionFactory.getExecutableSharedParameterTypes(method)); var isStatic = Modifier.isStatic(method.getModifiers()); var dmh = isStatic ? JLIA.findStatic(method.getDeclaringClass(), method.getName(), mtype) : JLIA.findVirtual(method.getDeclaringClass(), method.getName(), mtype); @@ -191,7 +192,7 @@ private static MethodHandle getDirectMethod(Method method, boolean callerSensiti private static MethodHandle findCallerSensitiveAdapter(Method method) throws IllegalAccessException { String name = method.getName(); // append a Class parameter - MethodType mtype = methodType(method.getReturnType(), method.getParameterTypes()) + MethodType mtype = methodType(method.getReturnType(), reflectionFactory.getExecutableSharedParameterTypes(method)) .appendParameterTypes(Class.class); boolean isStatic = Modifier.isStatic(method.getModifiers()); @@ -303,29 +304,43 @@ static void ensureClassInitialized(Class defc) { /* * Returns true if NativeAccessor should be used. + * + * Native accessor, i.e. VM reflection implementation, is used if one of + * the following conditions is met: + * 1. during VM early startup before method handle support is fully initialized + * 2. -Djdk.reflect.useNativeAccessorOnly=true is set + * 3. a signature polymorphic method + * 4. the member takes a variable number of arguments and the last parameter + * is not an array (see details below) + * 5. the member's method type has an arity >= 255 + * + * Conditions 3-5 are due to the restrictions of method handles. + * Otherwise, direct invocation of method handles is used. */ private static boolean useNativeAccessor(Executable member) { if (!VM.isJavaLangInvokeInited()) return true; - if (Modifier.isNative(member.getModifiers())) + if (ReflectionFactory.useNativeAccessorOnly()) // for testing only return true; - if (ReflectionFactory.useNativeAccessorOnly()) // for testing only + // java.lang.invoke cannot find the underlying native stubs of signature + // polymorphic methods that core reflection must invoke. + // Fall back to use the native implementation instead. + if (member instanceof Method method && isSignaturePolymorphicMethod(method)) return true; - // MethodHandle::withVarargs on a member with varargs modifier bit set - // verifies that the last parameter of the member must be an array type. - // The JVMS does not require the last parameter descriptor of the method descriptor - // is an array type if the ACC_VARARGS flag is set in the access_flags item. - // Hence the reflection implementation does not check the last parameter type - // if ACC_VARARGS flag is set. Workaround this by invoking through - // the native accessor. + // For members with ACC_VARARGS bit set, MethodHandles produced by lookup + // always have variable arity set and hence the last parameter of the member + // must be an array type. Such restriction does not exist in core reflection + // and the JVM, which always use fixed-arity invocations. Fall back to use + // the native implementation instead. int paramCount = member.getParameterCount(); if (member.isVarArgs() && - (paramCount == 0 || !(member.getParameterTypes()[paramCount-1].isArray()))) { + (paramCount == 0 || !(reflectionFactory.getExecutableSharedParameterTypes(member)[paramCount-1].isArray()))) { return true; } + // A method handle cannot be created if its type has an arity >= 255 // as the method handle's invoke method consumes an extra argument // of the method handle itself. Fall back to use the native implementation. @@ -345,7 +360,7 @@ private static boolean useNativeAccessor(Executable member) { */ private static int slotCount(Executable member) { int slots = 0; - Class[] ptypes = member.getParameterTypes(); + Class[] ptypes = reflectionFactory.getExecutableSharedParameterTypes(member); for (Class ptype : ptypes) { if (ptype == double.class || ptype == long.class) { slots++; @@ -355,6 +370,31 @@ private static int slotCount(Executable member) { (Modifier.isStatic(member.getModifiers()) ? 0 : 1); } + /** + * Signature-polymorphic methods. Lookup has special rules for these methods, + * but core reflection must observe them as they are declared, and reflective + * invocation must invoke the native method stubs that throw UOE. + * + * @param method the method to check + * @return {@code true} if this method is signature polymorphic + * @jls 15.12.3 Compile-Time Step 3: Is the Chosen Method Appropriate? + * @jvms 2.9.3 Signature Polymorphic Methods + */ + public static boolean isSignaturePolymorphicMethod(Method method) { + // ACC_NATIVE and ACC_VARARGS + if (!method.isVarArgs() || !Modifier.isNative(method.getModifiers())) { + return false; + } + // Declared in MethodHandle or VarHandle + var declaringClass = method.getDeclaringClass(); + if (declaringClass != MethodHandle.class && declaringClass != VarHandle.class) { + return false; + } + // Single parameter of declared type Object[] + Class[] parameters = reflectionFactory.getExecutableSharedParameterTypes(method); + return parameters.length == 1 && parameters[0] == Object[].class; + } + /* * Delay initializing these static fields until java.lang.invoke is fully initialized. */ @@ -363,4 +403,5 @@ static class LazyStaticHolder { } private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + private static final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); } diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 5bfc253c6bab..a2cefbddcfae 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.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 @@ -1864,22 +1864,7 @@ private void implCloseBlockingMode() throws IOException { registry.invalidateAll(); if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (reader != 0 || writer != 0) { - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } - } + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java b/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java index 1943a3c05698..9b65310784ab 100644 --- a/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java +++ b/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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,8 @@ import java.io.FileDescriptor; import java.io.IOException; +import jdk.internal.access.JavaIOFileDescriptorAccess; +import jdk.internal.access.SharedSecrets; /** * Allows different platforms to call different native methods @@ -34,6 +36,7 @@ */ abstract class NativeDispatcher { + private static final JavaIOFileDescriptorAccess JIOFDA = SharedSecrets.getJavaIOFileDescriptorAccess(); abstract int read(FileDescriptor fd, long address, int len) throws IOException; @@ -69,11 +72,28 @@ abstract long writev(FileDescriptor fd, long address, int len) abstract void close(FileDescriptor fd) throws IOException; - // Prepare the given fd for closing by duping it to a known internal fd - // that's already closed. This is necessary on some operating systems - // (Solaris and Linux) to prevent fd recycling. - // - void preClose(FileDescriptor fd) throws IOException { + /** + * Prepare the given file descriptor for closing. If a virtual thread is blocked + * on the file descriptor then it is unparked so that it stops polling. On Unix systems, + * if a platform thread is blocked on the file descriptor then the file descriptor is + * dup'ed to a special fd and the thread signalled so that the syscall fails with EINTR. + */ + final void preClose(FileDescriptor fd, long reader, long writer) throws IOException { + if (NativeThread.isVirtualThread(reader) || NativeThread.isVirtualThread(writer)) { + int fdVal = JIOFDA.get(fd); + Poller.stopPoll(fdVal); + } + if (NativeThread.isNativeThread(reader) || NativeThread.isNativeThread(writer)) { + implPreClose(fd, reader, writer); + } + } + + /** + * This method does nothing by default. On Unix systems the file descriptor is dup'ed + * to a special fd and native threads signalled. + */ + + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { // Do nothing by default; this is only needed on Unix } diff --git a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java index b9885a36fa89..58cd54fd2876 100644 --- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, 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 @@ -900,20 +900,7 @@ protected void close() throws IOException { // then the socket is pre-closed and the thread(s) signalled. The // last thread will close the file descriptor. if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal(fd)); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 98ab7a81e3d2..0a812229cc96 100644 --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -604,15 +604,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 1b333d569486..7ad62c076f8f 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -1060,20 +1060,8 @@ private void implCloseBlockingMode() throws IOException { } if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (NativeThread.isVirtualThread(reader) - || NativeThread.isVirtualThread(writer)) { - Poller.stopPoll(fdVal); - } - if (NativeThread.isNativeThread(reader) - || NativeThread.isNativeThread(writer)) { - nd.preClose(fd); - if (NativeThread.isNativeThread(reader)) - NativeThread.signal(reader); - if (NativeThread.isNativeThread(writer)) - NativeThread.signal(writer); - } + // prepare file descriptor for closing + nd.preClose(fd, readerThread, writerThread); } } } diff --git a/src/java.base/share/classes/sun/security/provider/MD4.java b/src/java.base/share/classes/sun/security/provider/MD4.java index 80cd85a83787..9862d46e57e7 100644 --- a/src/java.base/share/classes/sun/security/provider/MD4.java +++ b/src/java.base/share/classes/sun/security/provider/MD4.java @@ -78,13 +78,8 @@ public Void run() { }); } - public static MessageDigest getInstance() { - try { - return MessageDigest.getInstance("MD4", md4Provider); - } catch (NoSuchAlgorithmException e) { - // should never occur - throw new ProviderException(e); - } + public static MessageDigest getInstance() throws NoSuchAlgorithmException { + return MessageDigest.getInstance("MD4", md4Provider); } // Standard constructor, creates a new MD4 instance. diff --git a/src/java.base/share/classes/sun/security/ssl/Finished.java b/src/java.base/share/classes/sun/security/ssl/Finished.java index 7aef02d65e0d..4241fd0b5524 100644 --- a/src/java.base/share/classes/sun/security/ssl/Finished.java +++ b/src/java.base/share/classes/sun/security/ssl/Finished.java @@ -1147,7 +1147,9 @@ private void onConsumeFinished(ServerHandshakeContext shc, // // produce - NewSessionTicket.t13PosthandshakeProducer.produce(shc); + if (SSLConfiguration.serverNewSessionTicketCount > 0) { + NewSessionTicket.t13PosthandshakeProducer.produce(shc); + } } } diff --git a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java index 5c2a09b7c034..b3155f5170a8 100644 --- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java +++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, 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 @@ -187,7 +187,7 @@ boolean isCookieValid(ServerHandshakeContext context, byte[] secret; d10ManagerLock.lock(); try { - if (((cookieVersion >> 24) & 0xFF) == cookie[0]) { + if ((byte) ((cookieVersion >> 24) & 0xFF) == cookie[0]) { secret = cookieSecret; } else { secret = legacySecret; // including out of window cookies diff --git a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java index 0655b0e14ee1..8be021b41114 100644 --- a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java +++ b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ package sun.security.ssl; import java.io.IOException; -import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.text.MessageFormat; +import java.util.Arrays; import java.util.Locale; import javax.crypto.SecretKey; import javax.net.ssl.SSLHandshakeException; @@ -118,11 +118,6 @@ static final class T12NewSessionTicketMessage extends NewSessionTicketMessage { this.ticket = Record.getBytes16(m); } - @Override - public SSLHandshake handshakeType() { - return NEW_SESSION_TICKET; - } - @Override public int messageLength() { return 4 + // ticketLifetime @@ -221,11 +216,6 @@ static final class T13NewSessionTicketMessage extends NewSessionTicketMessage { this.extensions = new SSLExtensions(this, m, supportedExtensions); } - @Override - public SSLHandshake handshakeType() { - return NEW_SESSION_TICKET; - } - int getTicketAgeAdd() { return ticketAgeAdd; } @@ -301,7 +291,7 @@ private static SecretKey derivePreSharedKey(CipherSuite.HashAlg hashAlg, "tls13 resumption".getBytes(), nonce, hashAlg.hashLength); return hkdf.expand(resumptionMasterSecret, hkdfInfo, hashAlg.hashLength, "TlsPreSharedKey"); - } catch (GeneralSecurityException gse) { + } catch (GeneralSecurityException gse) { throw new SSLHandshakeException("Could not derive PSK", gse); } } @@ -332,8 +322,7 @@ public byte[] produce(ConnectionContext context) throws IOException { // Is this session resumable? if (!hc.handshakeSession.isRejoinable()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "No session ticket produced: " + + SSLLogger.fine("No session ticket produced: " + "session is not resumable"); } @@ -351,8 +340,7 @@ public byte[] produce(ConnectionContext context) throws IOException { if (pkemSpec == null || !pkemSpec.contains(PskKeyExchangeMode.PSK_DHE_KE)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "No session ticket produced: " + + SSLLogger.fine("No session ticket produced: " + "client does not support psk_dhe_ke"); } @@ -363,8 +351,7 @@ public byte[] produce(ConnectionContext context) throws IOException { // using an allowable PSK exchange key mode. if (!hc.handshakeSession.isPSKable()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "No session ticket produced: " + + SSLLogger.fine("No session ticket produced: " + "No session ticket allowed in this session"); } @@ -375,76 +362,113 @@ public byte[] produce(ConnectionContext context) throws IOException { // get a new session ID SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) hc.sslContext.engineGetServerSessionContext(); - SessionId newId = new SessionId(true, - hc.sslContext.getSecureRandom()); - - SecretKey resumptionMasterSecret = - hc.handshakeSession.getResumptionMasterSecret(); - if (resumptionMasterSecret == null) { + int sessionTimeoutSeconds = sessionCache.getSessionTimeout(); + if (sessionTimeoutSeconds > MAX_TICKET_LIFETIME) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "No session ticket produced: " + - "no resumption secret"); + SSLLogger.fine("No session ticket produced: " + + "session timeout is too long"); } return null; } - // construct the PSK and handshake message - BigInteger nonce = hc.handshakeSession.incrTicketNonceCounter(); - byte[] nonceArr = nonce.toByteArray(); - SecretKey psk = derivePreSharedKey( - hc.negotiatedCipherSuite.hashAlg, - resumptionMasterSecret, nonceArr); - - int sessionTimeoutSeconds = sessionCache.getSessionTimeout(); - if (sessionTimeoutSeconds > MAX_TICKET_LIFETIME) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "No session ticket produced: " + - "session timeout"); + // Send NewSessionTickets to the client based + if (SSLConfiguration.serverNewSessionTicketCount > 0) { + int i = 0; + NewSessionTicketMessage nstm; + while (i < SSLConfiguration.serverNewSessionTicketCount) { + nstm = generateNST(hc, sessionCache); + if (nstm == null) { + break; + } + nstm.write(hc.handshakeOutput); + i++; } - return null; + hc.handshakeOutput.flush(); + } + /* + * With large NST counts, a client that quickly closes after + * TLS Finished completes can cause SocketExceptions such as: + * Windows servers read-side throwing SocketException: + * "An established connection was aborted by the software in + * your host machine", which relates to error WSAECONNABORTED. + * A SocketException caused by a "broken pipe" has been observed on + * other systems. + * These are very unlikely situations when client and server are on + * different machines. + * + * RFC 8446 does not put requirements when an NST needs to be + * sent, but it should be sent very soon after TLS Finished for + * clients that will quickly resume to create more sessions. + * TLS 1.3 is different from TLS 1.2, there is more data the client + * should be aware of + */ + + // See note on TransportContext.needHandshakeFinishedStatus. + // + // Reset the needHandshakeFinishedStatus flag. The delivery + // of this post-handshake message will indicate the FINISHED + // handshake status. It is not needed to have a follow-on + // SSLEngine.wrap() any longer. + if (hc.conContext.needHandshakeFinishedStatus) { + hc.conContext.needHandshakeFinishedStatus = false; } - NewSessionTicketMessage nstm = null; + // clean the post handshake context + hc.conContext.finishPostHandshake(); + + // The message has been delivered. + return null; + } + + private NewSessionTicketMessage generateNST(HandshakeContext hc, + SSLSessionContextImpl sessionCache) throws IOException { + + NewSessionTicketMessage nstm; + SessionId newId = new SessionId(true, + hc.sslContext.getSecureRandom()); + + // construct the PSK and handshake message + byte[] nonce = hc.handshakeSession.incrTicketNonceCounter(); SSLSessionImpl sessionCopy = - new SSLSessionImpl(hc.handshakeSession, newId); - sessionCopy.setPreSharedKey(psk); + new SSLSessionImpl(hc.handshakeSession, newId); + sessionCopy.setPreSharedKey(derivePreSharedKey( + hc.negotiatedCipherSuite.hashAlg, + hc.handshakeSession.getResumptionMasterSecret(), nonce)); sessionCopy.setPskIdentity(newId.getId()); // If a stateless ticket is allowed, attempt to make one if (hc.statelessResumption && hc.handshakeSession.isStatelessable()) { nstm = new T13NewSessionTicketMessage(hc, - sessionTimeoutSeconds, + sessionCache.getSessionTimeout(), hc.sslContext.getSecureRandom(), - nonceArr, + nonce, new SessionTicketSpec().encrypt(hc, sessionCopy)); // If ticket construction failed, switch to session cache if (!nstm.isValid()) { hc.statelessResumption = false; } else { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "Produced NewSessionTicket stateless " + + SSLLogger.fine("Produced NewSessionTicket stateless " + "post-handshake message", nstm); } } + return nstm; } // If a session cache ticket is being used, make one if (!hc.statelessResumption || !hc.handshakeSession.isStatelessable()) { - nstm = new T13NewSessionTicketMessage(hc, sessionTimeoutSeconds, - hc.sslContext.getSecureRandom(), nonceArr, - newId.getId()); + nstm = new T13NewSessionTicketMessage(hc, + sessionCache.getSessionTimeout(), + hc.sslContext.getSecureRandom(), nonce, + newId.getId()); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine( - "Produced NewSessionTicket post-handshake message", - nstm); + SSLLogger.fine("Produced NewSessionTicket " + + "post-handshake message", nstm); } // create and cache the new session @@ -453,29 +477,13 @@ public byte[] produce(ConnectionContext context) throws IOException { hc.handshakeSession.addChild(sessionCopy); sessionCopy.setTicketAgeAdd(nstm.getTicketAgeAdd()); sessionCache.put(sessionCopy); + return nstm; } - // Output the handshake message. - if (nstm != null) { - // should never be null - nstm.write(hc.handshakeOutput); - hc.handshakeOutput.flush(); - - // See note on TransportContext.needHandshakeFinishedStatus. - // - // Reset the needHandshakeFinishedStatus flag. The delivery - // of this post-handshake message will indicate the FINISHED - // handshake status. It is not needed to have a follow-on - // SSLEngine.wrap() any longer. - if (hc.conContext.needHandshakeFinishedStatus) { - hc.conContext.needHandshakeFinishedStatus = false; - } + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine("No NewSessionTicket created"); } - // clean the post handshake context - hc.conContext.finishPostHandshake(); - - // The message has been delivered. return null; } } @@ -497,8 +505,9 @@ public byte[] produce(ConnectionContext context, ServerHandshakeContext shc = (ServerHandshakeContext)context; - // Is this session resumable? - if (!shc.handshakeSession.isRejoinable()) { + // Are new tickets allowed? If so, is this session resumable? + if (SSLConfiguration.serverNewSessionTicketCount == 0 || + !shc.handshakeSession.isRejoinable()) { return null; } @@ -578,7 +587,6 @@ public void consume(ConnectionContext context, "Discarding NewSessionTicket with lifetime " + nstm.ticketLifetime, nstm); } - sessionCache.remove(hc.handshakeSession.getSessionId()); return; } @@ -619,13 +627,19 @@ public void consume(ConnectionContext context, sessionCopy.setPreSharedKey(psk); sessionCopy.setTicketAgeAdd(nstm.getTicketAgeAdd()); sessionCopy.setPskIdentity(nstm.ticket); - sessionCache.put(sessionCopy); + sessionCache.put(sessionCopy, sessionCopy.isPSK()); + + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine("MultiNST PSK (Server): " + + Utilities.toHexString(Arrays.copyOf(nstm.ticket, 16))); + } // clean the post handshake context hc.conContext.finishPostHandshake(); } } + /* TLS 1.2 spec does not specify multiple NST behavior.*/ private static final class T12NewSessionTicketConsumer implements SSLConsumer { // Prevent instantiation of this class. @@ -674,8 +688,7 @@ public void consume(ConnectionContext context, hc.handshakeSession.setPskIdentity(nstm.ticket); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.fine("Consuming NewSessionTicket\n" + - nstm.toString()); + SSLLogger.fine("Consuming NewSessionTicket\n" + nstm); } } } diff --git a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java index 8e45f4593715..4751708e5dc8 100644 --- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java @@ -694,11 +694,13 @@ public byte[] produce(ConnectionContext context, //The session cannot be used again. Remove it from the cache. SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) chc.sslContext.engineGetClientSessionContext(); - sessionCache.remove(chc.resumingSession.getSessionId()); + sessionCache.remove(chc.resumingSession.getSessionId(), true); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine( "Found resumable session. Preparing PSK message."); + SSLLogger.fine( + "MultiNST PSK (Client): " + Utilities.toHexString(Arrays.copyOf(chc.pskIdentity, 16))); } List identities = new ArrayList<>(); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java index 79bc4faa0b59..85e100fc71fd 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,6 +119,11 @@ final class SSLConfiguration implements Cloneable { static final boolean enableDtlsResumeCookie = Utilities.getBooleanProperty( "jdk.tls.enableDtlsResumeCookie", true); + // Number of NewSessionTickets that will be sent by the server. + static final int serverNewSessionTicketCount; + // Default for NewSessionTickets + static final int SERVER_NST_DEFAULT = 1; + // Is the extended_master_secret extension supported? static { boolean supportExtendedMasterSecret = Utilities.getBooleanProperty( @@ -131,6 +136,33 @@ final class SSLConfiguration implements Cloneable { } } useExtendedMasterSecret = supportExtendedMasterSecret; + + /* + * jdk.tls.server.newSessionTicketCount system property + * Sets the number of NewSessionTickets sent to a TLS 1.3 resumption + * client. The value must be between 0 and 10. Default is defined by + * SERVER_NST_DEFAULT. + */ + Integer nstServerCount = GetIntegerAction.privilegedGetProperty( + "jdk.tls.server.newSessionTicketCount"); + if (nstServerCount == null || nstServerCount < 0 || + nstServerCount > 10) { + serverNewSessionTicketCount = SERVER_NST_DEFAULT; + if (nstServerCount != null && SSLLogger.isOn && + SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine( + "jdk.tls.server.newSessionTicketCount defaults to " + + SERVER_NST_DEFAULT + " as the property was not " + + "between 0 and 10"); + } + } else { + serverNewSessionTicketCount = nstServerCount; + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine( + "jdk.tls.server.newSessionTicketCount set to " + + serverNewSessionTicketCount); + } + } } SSLConfiguration(SSLContextImpl sslContext, boolean isClientMode) { diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java index 115cfc68185a..c653089ed12c 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -416,11 +416,12 @@ private HandshakeStatus tryNewSessionTicket( HandshakeStatus currentHandshakeStatus) throws IOException { // Don't bother to kickstart if handshaking is in progress, or if the // connection is not duplex-open. - if ((conContext.handshakeContext == null) && - conContext.protocolVersion.useTLS13PlusSpec() && - !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && - !conContext.isBroken) { + if (SSLConfiguration.serverNewSessionTicketCount > 0 && + conContext.handshakeContext == null && + conContext.protocolVersion.useTLS13PlusSpec() && + !conContext.isOutboundClosed() && + !conContext.isInboundClosed() && + !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger NST"); } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java index eb9eb75debe2..f3e22633ab4b 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,7 @@ final class SSLSessionContextImpl implements SSLSessionContext { private static final int DEFAULT_MAX_CACHE_SIZE = 20480; + private static final int DEFAULT_MAX_QUEUE_SIZE = 10; // Default lifetime of a session. 24 hours static final int DEFAULT_SESSION_TIMEOUT = 86400; @@ -87,14 +88,17 @@ final class SSLSessionContextImpl implements SSLSessionContext { cacheLimit = getDefaults(server); // default cache size // use soft reference - sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout); - sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout); if (server) { + sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout); + sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout); keyHashMap = new ConcurrentHashMap<>(); // Should be "randomly generated" according to RFC 5077, - // but doesn't necessarily has to be a true random number. + // but doesn't necessarily have to be a true random number. currentKeyID = new Random(System.nanoTime()).nextInt(); } else { + sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout); + sessionHostPortCache = Cache.newSoftMemoryQueue(cacheLimit, timeout, + DEFAULT_MAX_QUEUE_SIZE); keyHashMap = Map.of(); } } @@ -277,12 +281,22 @@ private static String getKey(String hostname, int port) { // time it created, which is a little longer than the expected. So // please do check isTimedout() while getting entry from the cache. void put(SSLSessionImpl s) { + put(s, false); + } + + /** + * Put an entry in the cache + * @param s SSLSessionImpl entry to be stored + * @param canQueue True if multiple entries may exist under one + * session entry. + */ + void put(SSLSessionImpl s, boolean canQueue) { sessionCache.put(s.getSessionId(), s); // If no hostname/port info is available, don't add this one. if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) { sessionHostPortCache.put( - getKey(s.getPeerHost(), s.getPeerPort()), s); + getKey(s.getPeerHost(), s.getPeerPort()), s, canQueue); } s.setContext(this); @@ -290,11 +304,17 @@ void put(SSLSessionImpl s) { // package-private method, remove a cached SSLSession void remove(SessionId key) { + remove(key, false); + } + void remove(SessionId key, boolean isClient) { SSLSessionImpl s = sessionCache.get(key); if (s != null) { sessionCache.remove(key); - sessionHostPortCache.remove( + // A client keeps the cache entry for queued NST resumption. + if (!isClient) { + sessionHostPortCache.remove( getKey(s.getPeerHost(), s.getPeerPort())); + } } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java index de9224389809..5db1175062f3 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -39,7 +39,6 @@ import java.util.Queue; import java.util.Collection; import java.util.Collections; -import java.util.Enumeration; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -133,7 +132,11 @@ final class SSLSessionImpl extends ExtendedSSLSession { private final List requestedServerNames; // Counter used to create unique nonces in NewSessionTicket - private BigInteger ticketNonceCounter = BigInteger.ONE; + private byte ticketNonceCounter = 1; + + // This boolean is true when a new set of NewSessionTickets are needed after + // the initial ones sent after the handshake. + boolean updateNST = false; // The endpoint identification algorithm used to check certificates // in this session. @@ -471,7 +474,12 @@ final class SSLSessionImpl extends ExtendedSSLSession { b = Record.getBytes16(buf); this.preSharedKey = new SecretKeySpec(b, alg); // Get identity len - this.pskIdentity = Record.getBytes8(buf); + i = Record.getInt8(buf); + if (i > 0) { + this.pskIdentity = Record.getBytes8(buf); + } else { + this.pskIdentity = null; + } break; default: throw new SSLException("Failed local certs of session."); @@ -685,14 +693,12 @@ void setPskIdentity(byte[] pskIdentity) { this.pskIdentity = pskIdentity; } - BigInteger incrTicketNonceCounter() { - BigInteger result = ticketNonceCounter; - ticketNonceCounter = ticketNonceCounter.add(BigInteger.ONE); - return result; + byte[] incrTicketNonceCounter() { + return new byte[] {ticketNonceCounter++}; } boolean isPSKable() { - return (ticketNonceCounter.compareTo(BigInteger.ZERO) > 0); + return (ticketNonceCounter > 0); } /** @@ -751,6 +757,10 @@ byte[] getPskIdentity() { return pskIdentity; } + public boolean isPSK() { + return (pskIdentity != null && pskIdentity.length > 0); + } + void setPeerCertificates(X509Certificate[] peer) { if (peerCerts == null) { peerCerts = peer; @@ -1203,7 +1213,6 @@ public void invalidate() { * sessions can be shared across different protection domains. */ private final ConcurrentHashMap boundValues; - boolean updateNST; /** * Assigns a session value. Session change events are given if diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index d8494595911c..44acbfa6debd 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1319,7 +1319,6 @@ public void write(byte[] b, } // Check if NewSessionTicket PostHandshake message needs to be sent if (conContext.conSession.updateNST) { - conContext.conSession.updateNST = false; tryNewSessionTicket(); } } @@ -1555,15 +1554,17 @@ private void tryKeyUpdate() throws IOException { private void tryNewSessionTicket() throws IOException { // Don't bother to kickstart if handshaking is in progress, or if the // connection is not duplex-open. - if (!conContext.sslConfig.isClientMode && - conContext.protocolVersion.useTLS13PlusSpec() && - conContext.handshakeContext == null && - !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && - !conContext.isBroken) { + if (SSLConfiguration.serverNewSessionTicketCount > 0 && + !conContext.sslConfig.isClientMode && + conContext.protocolVersion.useTLS13PlusSpec() && + conContext.handshakeContext == null && + !conContext.isOutboundClosed() && + !conContext.isInboundClosed() && + !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger new session ticket"); } + conContext.conSession.updateNST = false; NewSessionTicket.t13PosthandshakeProducer.produce( new PostHandshakeContext(conContext)); } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java index 3b0473d4eb0c..a7809754ed03 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -168,12 +168,12 @@ void encodeHandshake(byte[] source, for (int limit = (offset + length); offset < limit;) { - int remains = (limit - offset) + (count - position); - int fragLen = Math.min(fragLimit, remains); + int remains = (limit - offset); + int fragLen = Math.min(fragLimit - count + position, remains); // use the buf of ByteArrayOutputStream write(source, offset, fragLen); - if (remains < fragLimit) { + if (remains < fragLen) { return; } diff --git a/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java index 28f32742a612..d3b4468d9907 100644 --- a/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, 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 @@ -48,8 +48,17 @@ protected AbstractAlgorithmConstraints(AlgorithmDecomposer decomposer) { // Get algorithm constraints from the specified security property. static Set getAlgorithms(String propertyName) { + return getAlgorithms(propertyName, false); + } + + // Get algorithm constraints from the specified security property or + // system property if allowSystemOverride == true. + static Set getAlgorithms(String propertyName, + boolean allowSystemOverride) { @SuppressWarnings("removal") - String property = AccessController.doPrivileged( + String property = allowSystemOverride ? + SecurityProperties.privilegedGetOverridable(propertyName) : + AccessController.doPrivileged( new PrivilegedAction() { @Override public String run() { @@ -74,7 +83,8 @@ public String run() { if (algorithmsInProperty == null) { return Collections.emptySet(); } - Set algorithmsInPropertySet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + Set algorithmsInPropertySet = + new TreeSet<>(String.CASE_INSENSITIVE_ORDER); algorithmsInPropertySet.addAll(Arrays.asList(algorithmsInProperty)); return algorithmsInPropertySet; } @@ -89,17 +99,17 @@ static boolean checkAlgorithm(Set algorithms, String algorithm, return false; } - // decompose the algorithm into sub-elements - Set elements = decomposer.decompose(algorithm); + if (decomposer != null) { + // decompose the algorithm into sub-elements + Set elements = decomposer.decompose(algorithm); - // check the element of the elements - for (String element : elements) { - if (algorithms.contains(element)) { - return false; + // check the element of the elements + for (String element : elements) { + if (algorithms.contains(element)) { + return false; + } } } - return true; } - } diff --git a/src/java.base/share/classes/sun/security/util/Cache.java b/src/java.base/share/classes/sun/security/util/Cache.java index 23d6e0013ba1..a8449f0fc277 100644 --- a/src/java.base/share/classes/sun/security/util/Cache.java +++ b/src/java.base/share/classes/sun/security/util/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,12 @@ package sun.security.util; +import javax.net.ssl.SSLSession; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; import java.util.*; -import java.lang.ref.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; /** * Abstract base class and factory for caches. A cache is a key-value mapping. @@ -90,6 +94,15 @@ protected Cache() { */ public abstract void put(K key, V value); + /** + * Add V to the cache with the option to use a QueueCacheEntry if the + * cache is configured for it. If the cache is not configured for a queue, + * V will silently add the entry directly. + */ + public void put(K key, V value, boolean canQueue) { + put(key, value); + } + /** * Get a value from the cache. */ @@ -137,6 +150,11 @@ public static Cache newSoftMemoryCache(int size, int timeout) { return new MemoryCache<>(true, size, timeout); } + public static Cache newSoftMemoryQueue(int size, int timeout, + int maxQueueSize) { + return new MemoryCache<>(true, size, timeout, maxQueueSize); + } + /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by standard references. @@ -248,13 +266,12 @@ public void accept(CacheVisitor visitor) { class MemoryCache extends Cache { - private static final float LOAD_FACTOR = 0.75f; - - // XXXX + // Debugging private static final boolean DEBUG = false; private final Map> cacheMap; private int maxSize; + final private int maxQueueSize; private long lifetime; private long nextExpirationTime = Long.MAX_VALUE; @@ -263,18 +280,25 @@ class MemoryCache extends Cache { private final ReferenceQueue queue; public MemoryCache(boolean soft, int maxSize) { - this(soft, maxSize, 0); + this(soft, maxSize, 0, 0); } public MemoryCache(boolean soft, int maxSize, int lifetime) { + this(soft, maxSize, lifetime, 0); + } + + public MemoryCache(boolean soft, int maxSize, int lifetime, int qSize) { this.maxSize = maxSize; + this.maxQueueSize = qSize; this.lifetime = lifetime * 1000L; - if (soft) + if (soft) { this.queue = new ReferenceQueue<>(); - else + } else { this.queue = null; - - cacheMap = new LinkedHashMap<>(1, LOAD_FACTOR, true); + } + // LinkedHashMap is needed for its access order. 0.75f load factor is + // default. + cacheMap = new LinkedHashMap<>(1, 0.75f, true); } /** @@ -338,6 +362,10 @@ private void expungeExpiredEntries() { cnt++; } else if (nextExpirationTime > entry.getExpirationTime()) { nextExpirationTime = entry.getExpirationTime(); + // If this is a queue, check for some expired entries + if (entry instanceof QueueCacheEntry qe) { + qe.getQueue().removeIf(e -> !e.isValid(time)); + } } } if (DEBUG) { @@ -367,18 +395,60 @@ public synchronized void clear() { cacheMap.clear(); } - public synchronized void put(K key, V value) { + public void put(K key, V value) { + put(key, value, false); + } + + /** + * This puts an entry into the cacheMap. + * + * If canQueue is true, V will be added using a QueueCacheEntry which + * is added to cacheMap. If false, V is added to the cacheMap directly. + * The caller must keep a consistent canQueue value, mixing them can + * result in a queue being replaced with a single entry. + * + * This method is synchronized to avoid multiple QueueCacheEntry + * overwriting the same key. + * + * @param key key to the cacheMap + * @param value value to be stored + * @param canQueue can the value be put into a QueueCacheEntry + */ + public synchronized void put(K key, V value, boolean canQueue) { emptyQueue(); - long expirationTime = (lifetime == 0) ? 0 : - System.currentTimeMillis() + lifetime; + long expirationTime = + (lifetime == 0) ? 0 : System.currentTimeMillis() + lifetime; if (expirationTime < nextExpirationTime) { nextExpirationTime = expirationTime; } CacheEntry newEntry = newEntry(key, value, expirationTime, queue); - CacheEntry oldEntry = cacheMap.put(key, newEntry); - if (oldEntry != null) { - oldEntry.invalidate(); - return; + if (maxQueueSize == 0 || !canQueue) { + CacheEntry oldEntry = cacheMap.put(key, newEntry); + if (oldEntry != null) { + oldEntry.invalidate(); + } + } else { + CacheEntry entry = cacheMap.get(key); + switch (entry) { + case QueueCacheEntry qe -> { + qe.putValue(newEntry); + if (DEBUG) { + System.out.println("QueueCacheEntry= " + qe); + final AtomicInteger i = new AtomicInteger(1); + qe.queue.stream().forEach(e -> + System.out.println(i.getAndIncrement() + "= " + e)); + } + } + case null, default -> + cacheMap.put(key, new QueueCacheEntry<>(key, newEntry, + expirationTime, maxQueueSize)); + } + + if (DEBUG) { + System.out.println("Cache entry added: key=" + + key.toString() + ", class=" + + (entry != null ? entry.getClass().getName() : null)); + } } if (maxSize > 0 && cacheMap.size() > maxSize) { expungeExpiredEntries(); @@ -401,25 +471,37 @@ public synchronized V get(Object key) { if (entry == null) { return null; } - long time = (lifetime == 0) ? 0 : System.currentTimeMillis(); - if (!entry.isValid(time)) { + + if (lifetime > 0 && !entry.isValid(System.currentTimeMillis())) { + cacheMap.remove(key); if (DEBUG) { System.out.println("Ignoring expired entry"); } - cacheMap.remove(key); return null; } + + // If the value is a queue, return a queue entry. + if (entry instanceof QueueCacheEntry qe) { + V result = qe.getValue(lifetime); + if (qe.isEmpty()) { + removeImpl(key); + } + return result; + } return entry.getValue(); } public synchronized void remove(Object key) { emptyQueue(); + removeImpl(key); + } + + private void removeImpl(Object key) { CacheEntry entry = cacheMap.remove(key); if (entry != null) { entry.invalidate(); } } - public synchronized V pull(Object key) { emptyQueue(); CacheEntry entry = cacheMap.remove(key); @@ -550,9 +632,8 @@ public void invalidate() { } } - private static class SoftCacheEntry - extends SoftReference - implements CacheEntry { + private static class SoftCacheEntry extends SoftReference + implements CacheEntry { private K key; private long expirationTime; @@ -589,6 +670,116 @@ public void invalidate() { key = null; expirationTime = -1; } + + @Override + public String toString() { + if (get() instanceof SSLSession se) + return HexFormat.of().formatHex(se.getId()); + return super.toString(); + } } -} + /** + * This CacheEntry type allows multiple V entries to be stored in + * one key in the cacheMap. + * + * This implementation is need for TLS clients that receive multiple + * PSKs or NewSessionTickets for server resumption. + */ + private static class QueueCacheEntry implements CacheEntry { + + // Limit the number of queue entries. + private final int MAXQUEUESIZE; + + final boolean DEBUG = false; + private K key; + private long expirationTime; + final Queue> queue = new ConcurrentLinkedQueue<>(); + + QueueCacheEntry(K key, CacheEntry entry, long expirationTime, + int maxSize) { + this.key = key; + this.expirationTime = expirationTime; + this.MAXQUEUESIZE = maxSize; + queue.add(entry); + } + + public K getKey() { + return key; + } + + public V getValue() { + return getValue(0); + } + + public V getValue(long lifetime) { + long time = (lifetime == 0) ? 0 : System.currentTimeMillis(); + do { + var entry = queue.poll(); + if (entry == null) { + return null; + } + if (entry.isValid(time)) { + return entry.getValue(); + } + entry.invalidate(); + } while (!queue.isEmpty()); + + return null; + } + + public long getExpirationTime() { + return expirationTime; + } + + public void setExpirationTime(long time) { + expirationTime = time; + } + + public void putValue(CacheEntry entry) { + if (DEBUG) { + System.out.println("Added to queue (size=" + queue.size() + + "): " + entry.getKey().toString() + ", " + entry); + } + // Update the cache entry's expiration time to the latest entry. + // The getValue() calls will remove expired tickets. + expirationTime = entry.getExpirationTime(); + // Limit the number of queue entries, removing the oldest. + if (queue.size() >= MAXQUEUESIZE) { + queue.remove(); + } + queue.add(entry); + } + + public boolean isValid(long currentTime) { + boolean valid = (currentTime <= expirationTime) && !queue.isEmpty(); + if (!valid) { + invalidate(); + } + return valid; + } + + public boolean isValid() { + return isValid(System.currentTimeMillis()); + } + + public void invalidate() { + clear(); + key = null; + expirationTime = -1; + } + + public void clear() { + queue.forEach(CacheEntry::invalidate); + queue.clear(); + } + + public boolean isEmpty() { + return queue.isEmpty(); + } + + public Queue> getQueue() { + return queue; + } + } +} \ No newline at end of file diff --git a/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java new file mode 100644 index 000000000000..ad3beab350fa --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/CryptoAlgorithmConstraints.java @@ -0,0 +1,154 @@ +/* + * 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. 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.util; + +import java.lang.ref.SoftReference; +import java.security.AlgorithmParameters; +import java.security.CryptoPrimitive; +import java.security.Key; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class implements the algorithm constraints for the + * "jdk.crypto.disabledAlgorithms" security property. This security property + * can be overridden by the system property of the same name. See the + * java.security file for the syntax of the property value. + */ +public class CryptoAlgorithmConstraints extends AbstractAlgorithmConstraints { + private static final Debug debug = Debug.getInstance("jca"); + + // for validating the service + private static final Set SUPPORTED_SERVICES = + Set.of("Cipher", "KeyStore", "MessageDigest", "Signature"); + + // Disabled algorithm security property for JCE crypto services + private static final String PROPERTY_CRYPTO_DISABLED_ALGS = + "jdk.crypto.disabledAlgorithms"; + + private static class CryptoHolder { + static final CryptoAlgorithmConstraints CONSTRAINTS = + new CryptoAlgorithmConstraints(PROPERTY_CRYPTO_DISABLED_ALGS); + } + + private static void debug(String msg) { + if (debug != null) { + debug.println("CryptoAlgoConstraints: ", msg); + } + } + + public static boolean permits(String service, String algo) { + return CryptoHolder.CONSTRAINTS.cachedCheckAlgorithm( + service + "." + algo); + } + + private final Set disabledServices; // syntax is . + private volatile SoftReference> cacheRef = + new SoftReference<>(null); + + /** + * Initialize algorithm constraints with the specified security property + * {@code propertyName}. Note that if a system property of the same name + * is set, it overrides the security property. + * + * @param propertyName the security property name that define the disabled + * algorithm constraints + */ + CryptoAlgorithmConstraints(String propertyName) { + super(null); + disabledServices = getAlgorithms(propertyName, true); + String[] entries = disabledServices.toArray(new String[0]); + debug("Before " + Arrays.deepToString(entries)); + + for (String dk : entries) { + int idx = dk.indexOf("."); + if (idx < 1 || idx == dk.length() - 1) { + // wrong syntax: missing "." or empty service or algorithm + throw new IllegalArgumentException("Invalid entry: " + dk); + } + String service = dk.substring(0, idx); + String algo = dk.substring(idx + 1); + if (SUPPORTED_SERVICES.stream().anyMatch(e -> e.equalsIgnoreCase + (service))) { + KnownOIDs oid = KnownOIDs.findMatch(algo); + if (oid != null) { + debug("Add oid: " + oid.value()); + disabledServices.add(service + "." + oid.value()); + debug("Add oid stdName: " + oid.stdName()); + disabledServices.add(service + "." + oid.stdName()); + for (String a : oid.aliases()) { + debug("Add oid alias: " + a); + disabledServices.add(service + "." + a); + } + } + } else { + // unsupported service + throw new IllegalArgumentException("Invalid entry: " + dk); + } + } + debug("After " + Arrays.deepToString(disabledServices.toArray())); + } + + @Override + public final boolean permits(Set notUsed1, + String serviceDesc, AlgorithmParameters notUsed2) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + @Override + public final boolean permits(Set primitives, Key key) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + @Override + public final boolean permits(Set primitives, + String algorithm, Key key, AlgorithmParameters parameters) { + throw new UnsupportedOperationException("Unsupported permits() method"); + } + + // Return false if algorithm is found in the disabledServices Set. + // Otherwise, return true. + private boolean cachedCheckAlgorithm(String serviceDesc) { + Map cache; + if ((cache = cacheRef.get()) == null) { + synchronized (this) { + if ((cache = cacheRef.get()) == null) { + cache = new ConcurrentHashMap<>(); + cacheRef = new SoftReference<>(cache); + } + } + } + Boolean result = cache.get(serviceDesc); + if (result != null) { + return result; + } + result = checkAlgorithm(disabledServices, serviceDesc, null); + cache.put(serviceDesc, result); + return result; + } +} diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index 8cd0a03a365a..b1426c530557 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -185,7 +185,7 @@ public enum KnownOIDs { @Override boolean registerNames() { return false; } }, - RSA("1.2.840.113549.1.1.1"), // RSA encryption + RSA("1.2.840.113549.1.1.1", "RSA", "RSA/ECB/PKCS1Padding"), // RSA encryption MD2withRSA("1.2.840.113549.1.1.2"), MD5withRSA("1.2.840.113549.1.1.4"), diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 461e91115af6..f8ea3ecb1287 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -787,6 +787,54 @@ jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ ECDH, TLS_RSA_*, rsa_pkcs1_sha1 usage HandshakeSignature, \ ecdsa_sha1 usage HandshakeSignature, dsa_sha1 usage HandshakeSignature +# +# Algorithm restrictions for Java Crypto API services +# +# In some environments, certain algorithms may be undesirable for certain +# cryptographic services. For example, "MD2" is generally no longer considered +# to be a secure hash algorithm. This section describes the mechanism for +# disabling algorithms at the JCA/JCE level based on service name and algorithm +# name. +# +# If a system property of the same name is also specified, it supersedes the +# security property value defined here. +# +# The syntax of the disabled services string is described as follows: +# "DisabledService {, DisabledService}" +# +# DisabledService: +# Service.AlgorithmName +# +# Service: (one of the following, more services may be added later) +# Cipher | KeyStore | MessageDigest | Signature +# +# AlgorithmName: +# (see below) +# +# The "AlgorithmName" is the standard algorithm name of the disabled +# service. See the Java Security Standard Algorithm Names Specification +# for information about Standard Algorithm Names. Matching is +# performed using a case-insensitive exact matching rule. For Cipher service, +# its algorithm is the transformation string. +# +# Note: If the property value contains entries with invalid syntax or +# unsupported services at the time of checking, an ExceptionInInitializerError +# with a cause of IllegalArgumentException will be thrown. +# +# Note: The restriction is applied in the various getInstance(...) methods +# of the supported Service classes, i.e. Cipher, KeyStore, MessageDigest, +# and Signature. If the algorithm is disabled, a NoSuchAlgorithmException will +# be thrown by the getInstance methods of Cipher, MessageDigest, and Signature +# and a KeyStoreException by the getInstance methods of KeyStore. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# Example: +# jdk.crypto.disabledAlgorithms=Cipher.RSA/ECB/PKCS1Padding, MessageDigest.MD2 +# +#jdk.crypto.disabledAlgorithms= + # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. diff --git a/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java index 10a2098a0401..8f1692f0e4df 100644 --- a/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, 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 @@ -39,46 +39,43 @@ class DatagramDispatcher extends UnixDispatcher { IOUtil.load(); } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void close(FileDescriptor fd) throws IOException { - close0(fd); - } - - void preClose(FileDescriptor fd) throws IOException { - preClose0(fd); - } - + @Override void dup(FileDescriptor fd1, FileDescriptor fd2) throws IOException { dup0(fd1, fd2); } - static native int read0(FileDescriptor fd, long address, int len) + private static native int read0(FileDescriptor fd, long address, int len) throws IOException; - static native long readv0(FileDescriptor fd, long address, int len) + private static native long readv0(FileDescriptor fd, long address, int len) throws IOException; - static native int write0(FileDescriptor fd, long address, int len) + private static native int write0(FileDescriptor fd, long address, int len) throws IOException; - static native long writev0(FileDescriptor fd, long address, int len) + private static native long writev0(FileDescriptor fd, long address, int len) throws IOException; - static native void dup0(FileDescriptor fd1, FileDescriptor fd2) + private static native void dup0(FileDescriptor fd1, FileDescriptor fd2) throws IOException; } diff --git a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java index ab30b95986a0..2a5c77e08ddd 100644 --- a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java +++ b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,6 +86,17 @@ static boolean isVirtualThread(long tid) { return (tid == VIRTUAL_THREAD_ID); } + /** + * Return true if the operating system supports pending signals. If a signal is sent + * to a thread but cannot be delivered immediately then it will be delivered when the + * thread is in the appropriate state. + */ + static boolean supportPendingSignals() { + return supportPendingSignals0(); + } + + private static native boolean supportPendingSignals0(); + // Returns an opaque token representing the native thread underlying the // invoking Java thread. On systems that do not require signalling, this // method always returns 0. diff --git a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java index 7537c1a684fc..e53868748c6f 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,7 +42,7 @@ class SinkChannelImpl implements SelChImpl { // Used to make native read and write calls - private static final NativeDispatcher nd = new FileDispatcherImpl(); + private static final NativeDispatcher nd = new SocketDispatcher(); // The file descriptor associated with this channel private final FileDescriptor fd; @@ -152,15 +152,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java index 5b262fb58b7a..ebc4b2e8fbe7 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -43,6 +43,7 @@ class SocketDispatcher extends UnixDispatcher { * @throws sun.net.ConnectionResetException if connection reset is detected * @throws IOException if another I/O error occurs */ + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } @@ -54,26 +55,21 @@ int read(FileDescriptor fd, long address, int len) throws IOException { * @throws sun.net.ConnectionResetException if connection reset is detected * @throws IOException if another I/O error occurs */ + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void close(FileDescriptor fd) throws IOException { - close0(fd); - } - - void preClose(FileDescriptor fd) throws IOException { - preClose0(fd); - } - // -- Native methods -- private static native int read0(FileDescriptor fd, long address, int len) @@ -82,10 +78,10 @@ private static native int read0(FileDescriptor fd, long address, int len) private static native long readv0(FileDescriptor fd, long address, int len) throws IOException; - static native int write0(FileDescriptor fd, long address, int len) + private static native int write0(FileDescriptor fd, long address, int len) throws IOException; - static native long writev0(FileDescriptor fd, long address, int len) + private static native long writev0(FileDescriptor fd, long address, int len) throws IOException; static { diff --git a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java index 0ce85ec3b4e5..7760118ca02b 100644 --- a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java +++ b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,7 +42,7 @@ class SourceChannelImpl implements SelChImpl { // Used to make native read and write calls - private static final NativeDispatcher nd = new FileDispatcherImpl(); + private static final NativeDispatcher nd = new SocketDispatcher(); // The file descriptor associated with this channel private final FileDescriptor fd; @@ -152,15 +152,7 @@ private void implCloseBlockingMode() throws IOException { assert state < ST_CLOSING; state = ST_CLOSING; if (!tryClose()) { - long th = thread; - if (th != 0) { - if (NativeThread.isVirtualThread(th)) { - Poller.stopPoll(fdVal); - } else { - nd.preClose(fd); - NativeThread.signal(th); - } - } + nd.preClose(fd, thread, 0); } } } diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java index bc643100f9d7..4cdd0c400ec2 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.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 @@ -29,18 +29,34 @@ import java.io.IOException; abstract class UnixDispatcher extends NativeDispatcher { + private static final boolean SUPPORTS_PENDING_SIGNALS = NativeThread.supportPendingSignals(); + @Override void close(FileDescriptor fd) throws IOException { close0(fd); } - void preClose(FileDescriptor fd) throws IOException { + private void signalThreads(long reader, long writer) { + if (NativeThread.isNativeThread(reader)) + NativeThread.signal(reader); + if (NativeThread.isNativeThread(writer)) + NativeThread.signal(writer); + } + + @Override + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { + if (SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } preClose0(fd); + if (!SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } } - static native void close0(FileDescriptor fd) throws IOException; + private static native void close0(FileDescriptor fd) throws IOException; - static native void preClose0(FileDescriptor fd) throws IOException; + private static native void preClose0(FileDescriptor fd) throws IOException; static native void init(); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index cdccd90b54e7..5a7b5d8591ac 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -32,6 +32,7 @@ import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileStore; import java.nio.file.FileSystem; +import java.nio.file.FileSystemException; import java.nio.file.LinkOption; import java.nio.file.LinkPermission; import java.nio.file.Path; @@ -519,6 +520,8 @@ private void copyDirectory(UnixPath source, try { mkdir(target, attrs.mode()); } catch (UnixException x) { + if (x.errno() == EEXIST && flags.replaceExisting) + throw new FileSystemException(target.toString()); x.rethrowAsIOException(target); } @@ -665,6 +668,8 @@ void copyFile(UnixPath source, O_EXCL), attrs.mode()); } catch (UnixException x) { + if (x.errno() == EEXIST && flags.replaceExisting) + throw new FileSystemException(target.toString()); x.rethrowAsIOException(target); } @@ -783,6 +788,8 @@ private void copyLink(UnixPath source, } } } catch (UnixException x) { + if (x.errno() == EEXIST && flags.replaceExisting) + throw new FileSystemException(target.toString()); x.rethrowAsIOException(target); } } @@ -797,6 +804,8 @@ private void copySpecial(UnixPath source, try { mknod(target, attrs.mode(), attrs.rdev()); } catch (UnixException x) { + if (x.errno() == EEXIST && flags.replaceExisting) + throw new FileSystemException(target.toString()); x.rethrowAsIOException(target); } boolean done = false; diff --git a/src/java.base/unix/native/libnio/ch/NativeThread.c b/src/java.base/unix/native/libnio/ch/NativeThread.c index f273b951569f..d6d31b2b12b9 100644 --- a/src/java.base/unix/native/libnio/ch/NativeThread.c +++ b/src/java.base/unix/native/libnio/ch/NativeThread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,3 +88,12 @@ Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread) #endif JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed"); } + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_NativeThread_supportPendingSignals0(JNIEnv *env, jclass cl) { +#if defined(_AIX) + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} diff --git a/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java b/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java index c59dfabbcedd..de40be6cda11 100644 --- a/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/java.base/windows/classes/sun/nio/ch/DatagramDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, 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 @@ -36,22 +36,27 @@ class DatagramDispatcher extends NativeDispatcher { DatagramDispatcher() { } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } + @Override void close(FileDescriptor fd) throws IOException { SocketDispatcher.invalidateAndClose(fd); } diff --git a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java index 6ce751bddf71..a9c2a132cad1 100644 --- a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java +++ b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,26 +42,27 @@ class SocketDispatcher extends NativeDispatcher { SocketDispatcher() { } + @Override int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } + @Override long readv(FileDescriptor fd, long address, int len) throws IOException { return readv0(fd, address, len); } + @Override int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } + @Override long writev(FileDescriptor fd, long address, int len) throws IOException { return writev0(fd, address, len); } - void preClose(FileDescriptor fd) throws IOException { - throw new UnsupportedOperationException(); - } - + @Override void close(FileDescriptor fd) throws IOException { invalidateAndClose(fd); } diff --git a/src/java.base/windows/native/libjava/TimeZone_md.c b/src/java.base/windows/native/libjava/TimeZone_md.c index bcf616dad91d..fc9e29f01ac5 100644 --- a/src/java.base/windows/native/libjava/TimeZone_md.c +++ b/src/java.base/windows/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -435,7 +435,7 @@ static char *matchJavaTZ(const char *java_home_dir, char *tzName) strcpy(mapFileName, java_home_dir); strcat(mapFileName, MAPPINGS_FILE); - if ((fp = fopen(mapFileName, "r")) == NULL) { + if (fopen_s(&fp, mapFileName, "rt") != 0) { jio_fprintf(stderr, "can't open %s.\n", mapFileName); free((void *) mapFileName); return NULL; diff --git a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java index 03b36b3b819a..bc025b87f3c3 100644 --- a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -23,13 +23,22 @@ * questions. */ -/*- +/* * Reads xbitmap format images into a DIBitmap structure. */ package sun.awt.image; -import java.io.*; -import java.awt.image.*; +import java.awt.image.ImageConsumer; +import java.awt.image.IndexColorModel; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.Math.multiplyExact; /** * Parse files of the form: @@ -50,6 +59,8 @@ public class XbmImageDecoder extends ImageDecoder { ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME); + private static final int MAX_XBM_SIZE = 16384; + private static final int HEADER_SCAN_LIMIT = 100; public XbmImageDecoder(InputStreamImageSource src, InputStream is) { super(src, is); @@ -72,107 +83,155 @@ private static void error(String s1) throws ImageFormatException { * produce an image from the stream. */ public void produceImage() throws IOException, ImageFormatException { - char[] nm = new char[80]; - int c; - int i = 0; - int state = 0; int H = 0; int W = 0; int x = 0; int y = 0; - boolean start = true; + int n = 0; + int state = 0; byte[] raster = null; IndexColorModel model = null; - while (!aborted && (c = input.read()) != -1) { - if ('a' <= c && c <= 'z' || - 'A' <= c && c <= 'Z' || - '0' <= c && c <= '9' || c == '#' || c == '_') { - if (i < 78) - nm[i++] = (char) c; - } else if (i > 0) { - int nc = i; - i = 0; - if (start) { - if (nc != 7 || - nm[0] != '#' || - nm[1] != 'd' || - nm[2] != 'e' || - nm[3] != 'f' || - nm[4] != 'i' || - nm[5] != 'n' || - nm[6] != 'e') - { - error("Not an XBM file"); + + String matchRegex = "\\s*(0[xX])?((?:(?!,|\\};).)+)(,|\\};)"; + String replaceRegex = "0[xX]|,|\\s+|\\};"; + + String line; + int lineNum = 0; + + try (BufferedReader br = new BufferedReader(new InputStreamReader(input))) { + // loop to process XBM header - width, height and create raster + while (!aborted && (line = br.readLine()) != null + && lineNum <= HEADER_SCAN_LIMIT) { + lineNum++; + // process #define stmts + if (line.trim().startsWith("#define")) { + String[] token = line.split("\\s+"); + if (token.length != 3) { + error("Error while parsing define statement"); + } + try { + if (!token[2].isBlank() && state == 0) { + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 1; // after first dimension is set + } else if (!token[2].isBlank() && state == 1) { + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 2; // after second dimension is set + } + } catch (NumberFormatException nfe) { + // parseInt() can throw NFE + error("Error while parsing width or height."); } - start = false; } - if (nm[nc - 1] == 'h') - state = 1; /* expecting width */ - else if (nm[nc - 1] == 't' && nc > 1 && nm[nc - 2] == 'h') - state = 2; /* expecting height */ - else if (nc > 2 && state < 0 && nm[0] == '0' && nm[1] == 'x') { - int n = 0; - for (int p = 2; p < nc; p++) { - c = nm[p]; - if ('0' <= c && c <= '9') - c = c - '0'; - else if ('A' <= c && c <= 'Z') - c = c - 'A' + 10; - else if ('a' <= c && c <= 'z') - c = c - 'a' + 10; - else - c = 0; - n = n * 16 + c; + + if (state == 2) { + if (W <= 0 || H <= 0) { + error("Invalid values for width or height."); } - for (int mask = 1; mask <= 0x80; mask <<= 1) { - if (x < W) { - if ((n & mask) != 0) - raster[x] = 1; - else - raster[x] = 0; - } - x++; + if (multiplyExact(W, H) > MAX_XBM_SIZE) { + error("Large XBM file size." + + " Maximum allowed size: " + MAX_XBM_SIZE); } - if (x >= W) { - if (setPixels(0, y, W, 1, model, raster, 0, W) <= 0) { - return; - } - x = 0; - if (y++ >= H) { - break; - } + model = new IndexColorModel(8, 2, XbmColormap, + 0, false, 0); + setDimensions(W, H); + setColorModel(model); + setHints(XbmHints); + headerComplete(); + raster = new byte[W]; + state = 3; + break; + } + } + + if (state != 3) { + error("Width or Height of XBM file not defined"); + } + + boolean contFlag = false; + StringBuilder sb = new StringBuilder(); + + // loop to process image data + while (!aborted && (line = br.readLine()) != null) { + lineNum++; + + if (!contFlag) { + if (line.contains("[]")) { + contFlag = true; + } else { + continue; } + } + + int end = line.indexOf(';'); + if (end >= 0) { + sb.append(line, 0, end + 1); + break; } else { - int n = 0; - for (int p = 0; p < nc; p++) - if ('0' <= (c = nm[p]) && c <= '9') - n = n * 10 + c - '0'; - else { - n = -1; - break; - } - if (n > 0 && state > 0) { - if (state == 1) - W = n; + sb.append(line).append(System.lineSeparator()); + } + } + + String resultLine = sb.toString(); + int cutOffIndex = resultLine.indexOf('{'); + resultLine = resultLine.substring(cutOffIndex + 1); + + Matcher matcher = Pattern.compile(matchRegex).matcher(resultLine); + while (matcher.find()) { + if (y >= H) { + error("Scan size of XBM file exceeds" + + " the defined width x height"); + } + + int startIndex = matcher.start(); + int endIndex = matcher.end(); + String hexByte = resultLine.substring(startIndex, endIndex); + hexByte = hexByte.replaceAll("^\\s+", ""); + + if (!(hexByte.startsWith("0x") + || hexByte.startsWith("0X"))) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + hexByte = hexByte.replaceAll(replaceRegex, ""); + if (hexByte.length() != 2) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + + try { + n = Integer.parseInt(hexByte, 16); + } catch (NumberFormatException nfe) { + error("Error parsing hexadecimal at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + for (int mask = 1; mask <= 0x80; mask <<= 1) { + if (x < W) { + if ((n & mask) != 0) + raster[x] = 1; else - H = n; - if (W == 0 || H == 0) - state = 0; - else { - model = new IndexColorModel(8, 2, XbmColormap, - 0, false, 0); - setDimensions(W, H); - setColorModel(model); - setHints(XbmHints); - headerComplete(); - raster = new byte[W]; - state = -1; - } + raster[x] = 0; + } + x++; + } + + if (x >= W) { + int result = setPixels(0, y, W, 1, model, raster, 0, W); + if (result <= 0) { + error("Unexpected error occurred during setPixel()"); } + x = 0; + y++; } } + imageComplete(ImageConsumer.STATICIMAGEDONE, true); } - input.close(); - imageComplete(ImageConsumer.STATICIMAGEDONE, true); } } diff --git a/src/java.desktop/share/classes/sun/font/CompositeFont.java b/src/java.desktop/share/classes/sun/font/CompositeFont.java index bc136d75cfa1..8feb96a29482 100644 --- a/src/java.desktop/share/classes/sun/font/CompositeFont.java +++ b/src/java.desktop/share/classes/sun/font/CompositeFont.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, 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 @@ -88,7 +88,7 @@ public CompositeFont(String name, String[] compFileNames, /* * See if this is a windows locale which has a system EUDC font. - * If so add it as the final fallback component of the composite. + * If so add it as the first fallback component of the composite. * The caller could be responsible for this, but for now it seems * better that it is handled internally to the CompositeFont class. */ @@ -114,8 +114,8 @@ public CompositeFont(String name, String[] compFileNames, components[msCnt] = fm.getEUDCFont(); deferredInitialisation = new boolean[numSlots]; if (defer) { - for (int i=0; i MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons; + //4th and 5th buttons are for wheel and shouldn't be reported as buttons. + //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. + //If we have 3 physical buttons and a wheel, we report 3 buttons. + //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. + if (numberOfButtons >= 5) { + numberOfButtons -= 2; + } else if (numberOfButtons == 4 || numberOfButtons == 5) { numberOfButtons = 3; - } else { - numberOfButtons = getNumberOfButtonsImpl(); - numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons; - //4th and 5th buttons are for wheel and shouldn't be reported as buttons. - //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. - //If we have 3 physical buttons and a wheel, we report 3 buttons. - //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. - if (numberOfButtons >= 5) { - numberOfButtons -= 2; - } else if (numberOfButtons == 4 || numberOfButtons == 5) { - numberOfButtons = 3; - } } } //Assume don't have to re-query the number again and again. diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java index ab05247e4da1..602788b66115 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java @@ -66,9 +66,11 @@ public class ScreencastHelper { private static final int DELAY_BEFORE_SESSION_CLOSE = 2000; private static volatile TimerTask timerTask = null; - private static final Timer timerCloseSession - = new Timer("auto-close screencast session", true); + private static class TimerHolder { + private static final Timer timerCloseSession = + new Timer("auto-close screencast session", true); + } private ScreencastHelper() {} @@ -152,7 +154,7 @@ public void run() { } }; - timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE); + TimerHolder.timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE); } public static synchronized void getRGBPixels( diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java index 191a66bf6c89..8addd579bab0 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java @@ -252,6 +252,7 @@ public void run() { } private static WatchService watchService; + private static volatile boolean isWatcherThreadStarted = false; private static void setupWatch() { doPrivilegedRunnable(() -> { @@ -273,10 +274,6 @@ private static void setupWatch() { } } }); - - if (watchService != null) { - new WatcherThread(watchService).start(); - } } // called from native @@ -353,7 +350,27 @@ private static boolean readTokens(Path path) { return true; } + private static void startWatcherThreadIfNeeded() { + if (!isWatcherThreadStarted) { + // not sure if the double-checked locking is actually needed here + // the getTokens is only called from ScreencastHelper#getRGBPixels + // and ScreencastHelper#remoteDesktop* methods (which are synchronized), + // but it may change later. + synchronized (TokenStorage.class) { + if (!isWatcherThreadStarted) { + readTokens(PROPS_PATH); + if (watchService != null) { + new WatcherThread(watchService).start(); + } + isWatcherThreadStarted = true; + } + } + } + } + static Set getTokens(List affectedScreenBounds) { + startWatcherThreadIfNeeded(); + // We need an ordered set to store tokens // with exact matches at the beginning. LinkedHashSet result = new LinkedHashSet<>(); diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index 6c297426b0ff..a58ac85d9012 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -42,7 +42,6 @@ #include "debug_assert.h" static void *gtk3_libhandle = NULL; -static void *gthread_libhandle = NULL; static void transform_detail_string (const gchar *detail, GtkStyleContext *context); @@ -79,15 +78,6 @@ static void* dl_symbol(const char* name) return result; } -static void* dl_symbol_gthread(const char* name) -{ - void* result = dlsym(gthread_libhandle, name); - if (!result) - longjmp(j, NO_SYMBOL_EXCEPTION); - - return result; -} - gboolean gtk3_check(const char* lib_name, gboolean load) { if (gtk3_libhandle != NULL) { @@ -264,13 +254,6 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) return FALSE; } - gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) { - gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) - return FALSE; - } - if (setjmp(j) == 0) { fp_gtk_check_version = dl_symbol("gtk_check_version"); @@ -637,9 +620,6 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) dlclose(gtk3_libhandle); gtk3_libhandle = NULL; - dlclose(gthread_libhandle); - gthread_libhandle = NULL; - return NULL; } @@ -738,7 +718,6 @@ static int gtk3_unload() dlerror(); dlclose(gtk3_libhandle); - dlclose(gthread_libhandle); if ((gtk3_error = dlerror()) != NULL) { return FALSE; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 316a5834bd76..32dc3b0e82d9 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -2036,28 +2036,13 @@ JNIEnv* AwtToolkit::GetEnv() { BOOL AwtToolkit::GetScreenInsets(int screenNum, RECT * rect) { - /* if primary display */ - if (screenNum == 0) { - RECT rRW; - if (::SystemParametersInfo(SPI_GETWORKAREA,0,(void *) &rRW,0) == TRUE) { - rect->top = rRW.top; - rect->left = rRW.left; - rect->bottom = ::GetSystemMetrics(SM_CYSCREEN) - rRW.bottom; - rect->right = ::GetSystemMetrics(SM_CXSCREEN) - rRW.right; - return TRUE; - } - } - /* if additional display */ - else { - MONITORINFO *miInfo; - miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screenNum); - if (miInfo) { - rect->top = miInfo->rcWork.top - miInfo->rcMonitor.top; - rect->left = miInfo->rcWork.left - miInfo->rcMonitor.left; - rect->bottom = miInfo->rcMonitor.bottom - miInfo->rcWork.bottom; - rect->right = miInfo->rcMonitor.right - miInfo->rcWork.right; - return TRUE; - } + MONITORINFO *miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screenNum); + if (miInfo) { + rect->top = miInfo->rcWork.top - miInfo->rcMonitor.top; + rect->left = miInfo->rcWork.left - miInfo->rcMonitor.left; + rect->bottom = miInfo->rcMonitor.bottom - miInfo->rcWork.bottom; + rect->right = miInfo->rcMonitor.right - miInfo->rcWork.right; + return TRUE; } return FALSE; } diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java index b18f7d8eae1f..6e3ca59c0e8a 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java @@ -96,7 +96,7 @@ public KeyImpl(KerberosPrincipal principal, this.keyBytes = key.getBytes(); this.keyType = key.getEType(); } catch (KrbException e) { - throw new IllegalArgumentException(e.getMessage()); + throw new IllegalArgumentException("key creation error", e); } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java index ffe34ff33db4..1f6e98e50e85 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesDkCrypto.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,8 +108,6 @@ public byte[] stringToKey(char[] password, String salt, byte[] s2kparams) try { saltUtf8 = salt.getBytes(UTF_8); return stringToKey(password, saltUtf8, s2kparams); - } catch (Exception e) { - return null; } finally { if (saltUtf8 != null) { Arrays.fill(saltUtf8, (byte)0); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java index 5b58d35f750f..cb9e42b2deeb 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,8 +111,6 @@ public byte[] stringToKey(char[] password, String salt, byte[] s2kparams) try { saltUtf8 = salt.getBytes(UTF_8); return stringToKey(password, saltUtf8, s2kparams); - } catch (Exception e) { - return null; } finally { if (saltUtf8 != null) { Arrays.fill(saltUtf8, (byte)0); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java index a8bda6008f69..1dbaf3e32b26 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/ArcFourCrypto.java @@ -89,8 +89,6 @@ private byte[] stringToKey(char[] secret, byte[] opaque) MessageDigest md = sun.security.provider.MD4.getInstance(); md.update(passwd); digest = md.digest(); - } catch (Exception e) { - return null; } finally { if (passwd != null) { Arrays.fill(passwd, (byte)0); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java index bca72ab3f95d..c6b97db142e5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.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 @@ -26,12 +26,12 @@ * Constants for the project, mostly defined in the JVM specification. * * @since 6.0 (intended to replace the Constants interface) - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class Const { /** - * Java class file format Magic number (0xCAFEBABE) + * Java class file format Magic number: {@value}. * * @see The ClassFile Structure * in The Java Virtual Machine Specification @@ -39,201 +39,201 @@ public final class Const { public static final int JVM_CLASSFILE_MAGIC = 0xCAFEBABE; /** - * Major version number of class files for Java 1.1. + * Major version number of class files for Java 1.1: {@value}. * * @see #MINOR_1_1 */ public static final short MAJOR_1_1 = 45; /** - * Minor version number of class files for Java 1.1. + * Minor version number of class files for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MINOR_1_1 = 3; /** - * Major version number of class files for Java 1.2. + * Major version number of class files for Java 1.2: {@value}. * * @see #MINOR_1_2 */ public static final short MAJOR_1_2 = 46; /** - * Minor version number of class files for Java 1.2. + * Minor version number of class files for Java 1.2: {@value}. * * @see #MAJOR_1_2 */ public static final short MINOR_1_2 = 0; /** - * Major version number of class files for Java 1.2. + * Major version number of class files for Java 1.2: {@value}. * * @see #MINOR_1_2 */ public static final short MAJOR_1_3 = 47; /** - * Minor version number of class files for Java 1.3. + * Minor version number of class files for Java 1.3: {@value}. * * @see #MAJOR_1_3 */ public static final short MINOR_1_3 = 0; /** - * Major version number of class files for Java 1.3. + * Major version number of class files for Java 1.3: {@value}. * * @see #MINOR_1_3 */ public static final short MAJOR_1_4 = 48; /** - * Minor version number of class files for Java 1.4. + * Minor version number of class files for Java 1.4: {@value}. * * @see #MAJOR_1_4 */ public static final short MINOR_1_4 = 0; /** - * Major version number of class files for Java 1.4. + * Major version number of class files for Java 1.4: {@value}. * * @see #MINOR_1_4 */ public static final short MAJOR_1_5 = 49; /** - * Minor version number of class files for Java 1.5. + * Minor version number of class files for Java 1.5: {@value}. * * @see #MAJOR_1_5 */ public static final short MINOR_1_5 = 0; /** - * Major version number of class files for Java 1.6. + * Major version number of class files for Java 1.6: {@value}. * * @see #MINOR_1_6 */ public static final short MAJOR_1_6 = 50; /** - * Minor version number of class files for Java 1.6. + * Minor version number of class files for Java 1.6: {@value}. * * @see #MAJOR_1_6 */ public static final short MINOR_1_6 = 0; /** - * Major version number of class files for Java 1.7. + * Major version number of class files for Java 1.7: {@value}. * * @see #MINOR_1_7 */ public static final short MAJOR_1_7 = 51; /** - * Minor version number of class files for Java 1.7. + * Minor version number of class files for Java 1.7: {@value}. * * @see #MAJOR_1_7 */ public static final short MINOR_1_7 = 0; /** - * Major version number of class files for Java 1.8. + * Major version number of class files for Java 1.8: {@value}. * * @see #MINOR_1_8 */ public static final short MAJOR_1_8 = 52; /** - * Minor version number of class files for Java 1.8. + * Minor version number of class files for Java 1.8: {@value}. * * @see #MAJOR_1_8 */ public static final short MINOR_1_8 = 0; /** - * Major version number of class files for Java 9. + * Major version number of class files for Java 9: {@value}. * * @see #MINOR_9 */ public static final short MAJOR_9 = 53; /** - * Minor version number of class files for Java 9. + * Minor version number of class files for Java 9: {@value}. * * @see #MAJOR_9 */ public static final short MINOR_9 = 0; /** - * @deprecated Use {@link #MAJOR_9} instead + * @deprecated Use {@link #MAJOR_9} ({@value}) instead. */ @Deprecated public static final short MAJOR_1_9 = MAJOR_9; /** - * @deprecated Use {@link #MINOR_9} instead + * @deprecated Use {@link #MINOR_9} ({@value}) instead. */ @Deprecated public static final short MINOR_1_9 = MINOR_9; /** - * Major version number of class files for Java 10. + * Major version number of class files for Java 10: {@value}. * * @see #MINOR_10 */ public static final short MAJOR_10 = 54; /** - * Minor version number of class files for Java 10. + * Minor version number of class files for Java 10: {@value}. * * @see #MAJOR_10 */ public static final short MINOR_10 = 0; /** - * Major version number of class files for Java 11. + * Major version number of class files for Java 11: {@value}. * * @see #MINOR_11 */ public static final short MAJOR_11 = 55; /** - * Minor version number of class files for Java 11. + * Minor version number of class files for Java 11: {@value}. * * @see #MAJOR_11 */ public static final short MINOR_11 = 0; /** - * Major version number of class files for Java 12. + * Major version number of class files for Java 12: {@value}. * * @see #MINOR_12 */ public static final short MAJOR_12 = 56; /** - * Minor version number of class files for Java 12. + * Minor version number of class files for Java 12: {@value}. * * @see #MAJOR_12 */ public static final short MINOR_12 = 0; /** - * Major version number of class files for Java 13. + * Major version number of class files for Java 13: {@value}. * * @see #MINOR_13 */ public static final short MAJOR_13 = 57; /** - * Minor version number of class files for Java 13. + * Minor version number of class files for Java 13: {@value}. * * @see #MAJOR_13 */ public static final short MINOR_13 = 0; /** - * Minor version number of class files for Java 14. + * Minor version number of class files for Java 14: {@value}. * * @see #MAJOR_14 * @since 6.4.0 @@ -241,7 +241,7 @@ public final class Const { public static final short MINOR_14 = 0; /** - * Minor version number of class files for Java 15. + * Minor version number of class files for Java 15: {@value}. * * @see #MAJOR_15 * @since 6.6.0 @@ -249,7 +249,7 @@ public final class Const { public static final short MINOR_15 = 0; /** - * Minor version number of class files for Java 16. + * Minor version number of class files for Java 16: {@value}. * * @see #MAJOR_16 * @since 6.6.0 @@ -257,7 +257,7 @@ public final class Const { public static final short MINOR_16 = 0; /** - * Minor version number of class files for Java 17. + * Minor version number of class files for Java 17: {@value}. * * @see #MAJOR_17 * @since 6.6.0 @@ -265,7 +265,7 @@ public final class Const { public static final short MINOR_17 = 0; /** - * Minor version number of class files for Java 18. + * Minor version number of class files for Java 18: {@value}. * * @see #MAJOR_18 * @since 6.6.0 @@ -273,7 +273,7 @@ public final class Const { public static final short MINOR_18 = 0; /** - * Minor version number of class files for Java 19. + * Minor version number of class files for Java 19: {@value}. * * @see #MAJOR_19 * @since 6.6.0 @@ -281,7 +281,47 @@ public final class Const { public static final short MINOR_19 = 0; /** - * Major version number of class files for Java 14. + * Minor version number of class files for Java 20: {@value}. + * + * @see #MAJOR_20 + * @since 6.8.0 + */ + public static final short MINOR_20 = 0; + + /** + * Minor version number of class files for Java 21: {@value}. + * + * @see #MAJOR_21 + * @since 6.8.0 + */ + public static final short MINOR_21 = 0; + + /** + * Minor version number of class files for Java 22: {@value}. + * + * @see #MAJOR_22 + * @since 6.10.0 + */ + public static final short MINOR_22 = 0; + + /** + * Minor version number of class files for Java 23: {@value}. + * + * @see #MAJOR_23 + * @since 6.10.0 + */ + public static final short MINOR_23 = 0; + + /** + * Minor version number of class files for Java 24: {@value}. + * + * @see #MAJOR_24 + * @since 6.10.0 + */ + public static final short MINOR_24 = 0; + + /** + * Major version number of class files for Java 14: {@value}. * * @see #MINOR_14 * @since 6.4.0 @@ -289,7 +329,7 @@ public final class Const { public static final short MAJOR_14 = 58; /** - * Major version number of class files for Java 15. + * Major version number of class files for Java 15: {@value}. * * @see #MINOR_15 * @since 6.6.0 @@ -297,7 +337,7 @@ public final class Const { public static final short MAJOR_15 = 59; /** - * Major version number of class files for Java 16. + * Major version number of class files for Java 16: {@value}. * * @see #MINOR_16 * @since 6.6.0 @@ -305,7 +345,7 @@ public final class Const { public static final short MAJOR_16 = 60; /** - * Major version number of class files for Java 17. + * Major version number of class files for Java 17: {@value}. * * @see #MINOR_17 * @since 6.6.0 @@ -313,7 +353,7 @@ public final class Const { public static final short MAJOR_17 = 61; /** - * Major version number of class files for Java 18. + * Major version number of class files for Java 18: {@value}. * * @see #MINOR_18 * @since 6.6.0 @@ -321,7 +361,7 @@ public final class Const { public static final short MAJOR_18 = 62; /** - * Major version number of class files for Java 19. + * Major version number of class files for Java 19: {@value}. * * @see #MINOR_19 * @since 6.6.0 @@ -329,31 +369,71 @@ public final class Const { public static final short MAJOR_19 = 63; /** - * Default major version number. Class file is for Java 1.1. + * Major version number of class files for Java 20: {@value}. + * + * @see #MINOR_20 + * @since 6.8.0 + */ + public static final short MAJOR_20 = 64; + + /** + * Major version number of class files for Java 21: {@value}. + * + * @see #MINOR_21 + * @since 6.8.0 + */ + public static final short MAJOR_21 = 65; + + /** + * Major version number of class files for Java 22: {@value}. + * + * @see #MINOR_22 + * @since 6.10.0 + */ + public static final short MAJOR_22 = 66; + + /** + * Major version number of class files for Java 23: {@value}. + * + * @see #MINOR_23 + * @since 6.10.0 + */ + public static final short MAJOR_23 = 67; + + /** + * Major version number of class files for Java 24: {@value}. + * + * @see #MINOR_24 + * @since 6.10.0 + */ + public static final short MAJOR_24 = 68; + + /** + * Default major version number. Class file is for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MAJOR = MAJOR_1_1; /** - * Default major version number. Class file is for Java 1.1. + * Default major version number. Class file is for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MINOR = MINOR_1_1; /** - * Maximum value for an unsigned short. + * Maximum value for an unsigned short: {@value}. */ public static final int MAX_SHORT = 65535; // 2^16 - 1 /** - * Maximum value for an unsigned byte. + * Maximum value for an unsigned byte: {@value}. */ public static final int MAX_BYTE = 255; // 2^8 - 1 /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see Flag definitions for * Classes in the Java Virtual Machine Specification (Java SE 9 Edition). @@ -367,140 +447,140 @@ public final class Const { public static final short ACC_PUBLIC = 0x0001; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_PRIVATE = 0x0002; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_PROTECTED = 0x0004; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STATIC = 0x0008; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_FINAL = 0x0010; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_OPEN = 0x0020; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SUPER = 0x0020; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SYNCHRONIZED = 0x0020; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_TRANSITIVE = 0x0020; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_BRIDGE = 0x0040; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STATIC_PHASE = 0x0040; /** - * One of the access flags for fields. + * One of the access flags for fields: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_VOLATILE = 0x0040; /** - * One of the access flags for fields. + * One of the access flags for fields: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_TRANSIENT = 0x0080; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_VARARGS = 0x0080; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_NATIVE = 0x0100; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_INTERFACE = 0x0200; /** - * One of the access flags for methods or classes. + * One of the access flags for methods or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_ABSTRACT = 0x0400; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STRICT = 0x0800; /** - * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute. + * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SYNTHETIC = 0x1000; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_ANNOTATION = 0x2000; /** - * One of the access flags for fields or classes. + * One of the access flags for fields or classes: {@value}. * * @see #ACC_PUBLIC */ @@ -508,21 +588,21 @@ public final class Const { // Applies to classes compiled by new compilers only /** - * One of the access flags for MethodParameter or Module attributes. + * One of the access flags for MethodParameter or Module attributes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_MANDATED = (short) 0x8000; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_MODULE = (short) 0x8000; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC * @deprecated Use {@link #MAX_ACC_FLAG_I} @@ -531,7 +611,7 @@ public final class Const { public static final short MAX_ACC_FLAG = ACC_ENUM; /** - * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short. + * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short: {@value}. * * @see #ACC_PUBLIC * @since 6.4.0 @@ -553,7 +633,7 @@ public final class Const { public static final int ACCESS_NAMES_LENGTH = ACCESS_NAMES.length; /** - * Marks a constant pool entry as type UTF-8. + * Marks a constant pool entry as type UTF-8: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -566,7 +646,7 @@ public final class Const { */ /** - * Marks a constant pool entry as type Integer. + * Marks a constant pool entry as type Integer: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -574,7 +654,7 @@ public final class Const { public static final byte CONSTANT_Integer = 3; /** - * Marks a constant pool entry as type Float. + * Marks a constant pool entry as type Float: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -582,7 +662,7 @@ public final class Const { public static final byte CONSTANT_Float = 4; /** - * Marks a constant pool entry as type Long. + * Marks a constant pool entry as type Long: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -590,7 +670,7 @@ public final class Const { public static final byte CONSTANT_Long = 5; /** - * Marks a constant pool entry as type Double. + * Marks a constant pool entry as type Double: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -598,7 +678,7 @@ public final class Const { public static final byte CONSTANT_Double = 6; /** - * Marks a constant pool entry as a Class + * Marks a constant pool entry as a Class: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -606,7 +686,7 @@ public final class Const { public static final byte CONSTANT_Class = 7; /** - * Marks a constant pool entry as a Field Reference. + * Marks a constant pool entry as a Field Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -614,7 +694,7 @@ public final class Const { public static final byte CONSTANT_Fieldref = 9; /** - * Marks a constant pool entry as type String + * Marks a constant pool entry as type String: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -622,7 +702,7 @@ public final class Const { public static final byte CONSTANT_String = 8; /** - * Marks a constant pool entry as a Method Reference. + * Marks a constant pool entry as a Method Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -630,7 +710,7 @@ public final class Const { public static final byte CONSTANT_Methodref = 10; /** - * Marks a constant pool entry as an Interface Method Reference. + * Marks a constant pool entry as an Interface Method Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -638,7 +718,7 @@ public final class Const { public static final byte CONSTANT_InterfaceMethodref = 11; /** - * Marks a constant pool entry as a name and type. + * Marks a constant pool entry as a name and type: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -646,7 +726,7 @@ public final class Const { public static final byte CONSTANT_NameAndType = 12; /** - * Marks a constant pool entry as a Method Handle. + * Marks a constant pool entry as a Method Handle: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -654,7 +734,7 @@ public final class Const { public static final byte CONSTANT_MethodHandle = 15; /** - * Marks a constant pool entry as a Method Type. + * Marks a constant pool entry as a Method Type: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -662,16 +742,16 @@ public final class Const { public static final byte CONSTANT_MethodType = 16; /** - * Marks a constant pool entry as dynamically computed. + * Marks a constant pool entry as dynamically computed: {@value}. * - * @see Change request for JEP - * 309 + * @see The Constant Pool in The + * Java Virtual Machine Specification * @since 6.3 */ public static final byte CONSTANT_Dynamic = 17; /** - * Marks a constant pool entry as an Invoke Dynamic + * Marks a constant pool entry as an Invoke Dynamic: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -679,7 +759,7 @@ public final class Const { public static final byte CONSTANT_InvokeDynamic = 18; /** - * Marks a constant pool entry as a Module Reference. + * Marks a constant pool entry as a Module Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -688,7 +768,7 @@ public final class Const { public static final byte CONSTANT_Module = 19; /** - * Marks a constant pool entry as a Package Reference. + * Marks a constant pool entry as a Package Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -705,23 +785,23 @@ public final class Const { /** * The name of the static initializer, also called "class initialization method" or "interface - * initialization method". This is "<clinit>". + * initialization method". This is {@value}. */ public static final String STATIC_INITIALIZER_NAME = ""; /** * The name of every constructor method in a class, also called "instance initialization method". This is - * "<init>". + * {@value}. */ public static final String CONSTRUCTOR_NAME = ""; /** - * The names of the interfaces implemented by arrays + * The names of the interfaces implemented by arrays. */ private static final String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"}; /** - * Maximum Constant Pool entries. One of the limitations of the Java Virtual Machine. + * Maximum Constant Pool entries: {@value}. One of the limitations of the Java Virtual Machine. * * @see The Java Virtual * Machine Specification, Java SE 8 Edition, page 330, chapter 4.11. @@ -729,21 +809,25 @@ public final class Const { public static final int MAX_CP_ENTRIES = 65535; /** - * Maximum code size (plus one; the code size must be LESS than this) One of the limitations of the Java Virtual - * Machine. Note vmspec2 page 152 ("Limitations") says: "The amount of code per non-native, non-abstract method is - * limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute (4.7.3), in the - * LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken - * as an upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says: - * "The value of the code_length item must be less than 65536." The entry in the Limitations section has been removed - * from later versions of the spec; it is not present in the Java SE 8 edition. + * Maximum code size (plus one; the code size must be LESS than this): {@value}. + *

+ * One of the limitations of the Java Virtual Machine. Note vmspec2 page 152 ("Limitations") says: + *

+ *
"The amount of code per non-native, non-abstract method is limited to 65536 bytes by the sizes of the indices in the exception_table of the Code
+     * attribute (4.7.3), in the LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken as an
+     * upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says: "The value of the code_length item must be
+     * less than 65536."
+ *

+ * The entry in the Limitations section has been removed from later versions of the specification; it is not present in the Java SE 8 edition. + *

* - * @see The Java Virtual - * Machine Specification, Java SE 8 Edition, page 104, chapter 4.7. + * @see The Java Virtual Machine Specification, Java SE 8 + * Edition, page 104, chapter 4.7. */ public static final int MAX_CODE_SIZE = 65536; // bytes /** - * The maximum number of dimensions in an array ({@value}). One of the limitations of the Java Virtual Machine. + * The maximum number of dimensions in an array: {@value}. One of the limitations of the Java Virtual Machine. * * @see Field Descriptors in * The Java Virtual Machine Specification @@ -751,7 +835,7 @@ public final class Const { public static final int MAX_ARRAY_DIMENSIONS = 255; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -759,7 +843,7 @@ public final class Const { public static final short NOP = 0; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -767,7 +851,7 @@ public final class Const { public static final short ACONST_NULL = 1; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -775,7 +859,7 @@ public final class Const { public static final short ICONST_M1 = 2; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -783,7 +867,7 @@ public final class Const { public static final short ICONST_0 = 3; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -791,7 +875,7 @@ public final class Const { public static final short ICONST_1 = 4; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -799,7 +883,7 @@ public final class Const { public static final short ICONST_2 = 5; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -807,7 +891,7 @@ public final class Const { public static final short ICONST_3 = 6; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -815,7 +899,7 @@ public final class Const { public static final short ICONST_4 = 7; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -823,7 +907,7 @@ public final class Const { public static final short ICONST_5 = 8; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -831,7 +915,7 @@ public final class Const { public static final short LCONST_0 = 9; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -839,7 +923,7 @@ public final class Const { public static final short LCONST_1 = 10; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -847,7 +931,7 @@ public final class Const { public static final short FCONST_0 = 11; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -855,7 +939,7 @@ public final class Const { public static final short FCONST_1 = 12; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -863,7 +947,7 @@ public final class Const { public static final short FCONST_2 = 13; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -871,7 +955,7 @@ public final class Const { public static final short DCONST_0 = 14; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -879,7 +963,7 @@ public final class Const { public static final short DCONST_1 = 15; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -887,7 +971,7 @@ public final class Const { public static final short BIPUSH = 16; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -895,7 +979,7 @@ public final class Const { public static final short SIPUSH = 17; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -903,7 +987,7 @@ public final class Const { public static final short LDC = 18; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -911,7 +995,7 @@ public final class Const { public static final short LDC_W = 19; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -919,7 +1003,7 @@ public final class Const { public static final short LDC2_W = 20; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -927,7 +1011,7 @@ public final class Const { public static final short ILOAD = 21; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -935,7 +1019,7 @@ public final class Const { public static final short LLOAD = 22; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -943,7 +1027,7 @@ public final class Const { public static final short FLOAD = 23; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -951,7 +1035,7 @@ public final class Const { public static final short DLOAD = 24; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -959,7 +1043,7 @@ public final class Const { public static final short ALOAD = 25; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -967,7 +1051,7 @@ public final class Const { public static final short ILOAD_0 = 26; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -975,7 +1059,7 @@ public final class Const { public static final short ILOAD_1 = 27; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -983,7 +1067,7 @@ public final class Const { public static final short ILOAD_2 = 28; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -991,7 +1075,7 @@ public final class Const { public static final short ILOAD_3 = 29; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -999,7 +1083,7 @@ public final class Const { public static final short LLOAD_0 = 30; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1007,7 +1091,7 @@ public final class Const { public static final short LLOAD_1 = 31; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1015,7 +1099,7 @@ public final class Const { public static final short LLOAD_2 = 32; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1023,7 +1107,7 @@ public final class Const { public static final short LLOAD_3 = 33; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1031,7 +1115,7 @@ public final class Const { public static final short FLOAD_0 = 34; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1039,7 +1123,7 @@ public final class Const { public static final short FLOAD_1 = 35; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1047,7 +1131,7 @@ public final class Const { public static final short FLOAD_2 = 36; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1055,7 +1139,7 @@ public final class Const { public static final short FLOAD_3 = 37; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1063,7 +1147,7 @@ public final class Const { public static final short DLOAD_0 = 38; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1071,7 +1155,7 @@ public final class Const { public static final short DLOAD_1 = 39; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1079,7 +1163,7 @@ public final class Const { public static final short DLOAD_2 = 40; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1087,7 +1171,7 @@ public final class Const { public static final short DLOAD_3 = 41; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1095,7 +1179,7 @@ public final class Const { public static final short ALOAD_0 = 42; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1103,7 +1187,7 @@ public final class Const { public static final short ALOAD_1 = 43; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1111,7 +1195,7 @@ public final class Const { public static final short ALOAD_2 = 44; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1119,7 +1203,7 @@ public final class Const { public static final short ALOAD_3 = 45; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1127,7 +1211,7 @@ public final class Const { public static final short IALOAD = 46; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1135,7 +1219,7 @@ public final class Const { public static final short LALOAD = 47; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1143,7 +1227,7 @@ public final class Const { public static final short FALOAD = 48; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1151,7 +1235,7 @@ public final class Const { public static final short DALOAD = 49; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1159,7 +1243,7 @@ public final class Const { public static final short AALOAD = 50; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1167,7 +1251,7 @@ public final class Const { public static final short BALOAD = 51; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1175,7 +1259,7 @@ public final class Const { public static final short CALOAD = 52; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1183,7 +1267,7 @@ public final class Const { public static final short SALOAD = 53; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1191,7 +1275,7 @@ public final class Const { public static final short ISTORE = 54; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1199,7 +1283,7 @@ public final class Const { public static final short LSTORE = 55; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1207,7 +1291,7 @@ public final class Const { public static final short FSTORE = 56; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1215,7 +1299,7 @@ public final class Const { public static final short DSTORE = 57; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1223,7 +1307,7 @@ public final class Const { public static final short ASTORE = 58; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1231,7 +1315,7 @@ public final class Const { public static final short ISTORE_0 = 59; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1239,7 +1323,7 @@ public final class Const { public static final short ISTORE_1 = 60; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1247,7 +1331,7 @@ public final class Const { public static final short ISTORE_2 = 61; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1255,7 +1339,7 @@ public final class Const { public static final short ISTORE_3 = 62; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1263,7 +1347,7 @@ public final class Const { public static final short LSTORE_0 = 63; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1271,7 +1355,7 @@ public final class Const { public static final short LSTORE_1 = 64; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1279,7 +1363,7 @@ public final class Const { public static final short LSTORE_2 = 65; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1287,7 +1371,7 @@ public final class Const { public static final short LSTORE_3 = 66; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1295,7 +1379,7 @@ public final class Const { public static final short FSTORE_0 = 67; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1303,7 +1387,7 @@ public final class Const { public static final short FSTORE_1 = 68; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1311,7 +1395,7 @@ public final class Const { public static final short FSTORE_2 = 69; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1319,7 +1403,7 @@ public final class Const { public static final short FSTORE_3 = 70; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1327,7 +1411,7 @@ public final class Const { public static final short DSTORE_0 = 71; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1335,7 +1419,7 @@ public final class Const { public static final short DSTORE_1 = 72; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1343,7 +1427,7 @@ public final class Const { public static final short DSTORE_2 = 73; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1351,7 +1435,7 @@ public final class Const { public static final short DSTORE_3 = 74; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1359,7 +1443,7 @@ public final class Const { public static final short ASTORE_0 = 75; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1367,7 +1451,7 @@ public final class Const { public static final short ASTORE_1 = 76; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1375,7 +1459,7 @@ public final class Const { public static final short ASTORE_2 = 77; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1383,7 +1467,7 @@ public final class Const { public static final short ASTORE_3 = 78; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1391,7 +1475,7 @@ public final class Const { public static final short IASTORE = 79; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1399,7 +1483,7 @@ public final class Const { public static final short LASTORE = 80; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1407,7 +1491,7 @@ public final class Const { public static final short FASTORE = 81; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1415,7 +1499,7 @@ public final class Const { public static final short DASTORE = 82; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1423,7 +1507,7 @@ public final class Const { public static final short AASTORE = 83; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1431,7 +1515,7 @@ public final class Const { public static final short BASTORE = 84; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1439,7 +1523,7 @@ public final class Const { public static final short CASTORE = 85; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1447,7 +1531,7 @@ public final class Const { public static final short SASTORE = 86; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1455,7 +1539,7 @@ public final class Const { public static final short POP = 87; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1463,7 +1547,7 @@ public final class Const { public static final short POP2 = 88; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1471,7 +1555,7 @@ public final class Const { public static final short DUP = 89; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1479,7 +1563,7 @@ public final class Const { public static final short DUP_X1 = 90; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1487,7 +1571,7 @@ public final class Const { public static final short DUP_X2 = 91; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1495,7 +1579,7 @@ public final class Const { public static final short DUP2 = 92; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1503,7 +1587,7 @@ public final class Const { public static final short DUP2_X1 = 93; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1511,7 +1595,7 @@ public final class Const { public static final short DUP2_X2 = 94; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1519,7 +1603,7 @@ public final class Const { public static final short SWAP = 95; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1527,7 +1611,7 @@ public final class Const { public static final short IADD = 96; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1535,7 +1619,7 @@ public final class Const { public static final short LADD = 97; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1543,7 +1627,7 @@ public final class Const { public static final short FADD = 98; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1551,7 +1635,7 @@ public final class Const { public static final short DADD = 99; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1559,7 +1643,7 @@ public final class Const { public static final short ISUB = 100; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1567,7 +1651,7 @@ public final class Const { public static final short LSUB = 101; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1575,7 +1659,7 @@ public final class Const { public static final short FSUB = 102; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1583,7 +1667,7 @@ public final class Const { public static final short DSUB = 103; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1591,7 +1675,7 @@ public final class Const { public static final short IMUL = 104; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1599,7 +1683,7 @@ public final class Const { public static final short LMUL = 105; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1607,7 +1691,7 @@ public final class Const { public static final short FMUL = 106; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1615,7 +1699,7 @@ public final class Const { public static final short DMUL = 107; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1623,7 +1707,7 @@ public final class Const { public static final short IDIV = 108; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1631,7 +1715,7 @@ public final class Const { public static final short LDIV = 109; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1639,7 +1723,7 @@ public final class Const { public static final short FDIV = 110; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1647,7 +1731,7 @@ public final class Const { public static final short DDIV = 111; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1655,7 +1739,7 @@ public final class Const { public static final short IREM = 112; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1663,7 +1747,7 @@ public final class Const { public static final short LREM = 113; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1671,7 +1755,7 @@ public final class Const { public static final short FREM = 114; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1679,7 +1763,7 @@ public final class Const { public static final short DREM = 115; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1687,7 +1771,7 @@ public final class Const { public static final short INEG = 116; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1695,7 +1779,7 @@ public final class Const { public static final short LNEG = 117; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1703,7 +1787,7 @@ public final class Const { public static final short FNEG = 118; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1711,7 +1795,7 @@ public final class Const { public static final short DNEG = 119; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1719,7 +1803,7 @@ public final class Const { public static final short ISHL = 120; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1727,7 +1811,7 @@ public final class Const { public static final short LSHL = 121; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1735,7 +1819,7 @@ public final class Const { public static final short ISHR = 122; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1743,7 +1827,7 @@ public final class Const { public static final short LSHR = 123; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1751,7 +1835,7 @@ public final class Const { public static final short IUSHR = 124; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1759,7 +1843,7 @@ public final class Const { public static final short LUSHR = 125; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1767,7 +1851,7 @@ public final class Const { public static final short IAND = 126; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1775,7 +1859,7 @@ public final class Const { public static final short LAND = 127; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1783,7 +1867,7 @@ public final class Const { public static final short IOR = 128; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1791,7 +1875,7 @@ public final class Const { public static final short LOR = 129; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1799,7 +1883,7 @@ public final class Const { public static final short IXOR = 130; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1807,7 +1891,7 @@ public final class Const { public static final short LXOR = 131; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1815,7 +1899,7 @@ public final class Const { public static final short IINC = 132; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1823,7 +1907,7 @@ public final class Const { public static final short I2L = 133; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1831,7 +1915,7 @@ public final class Const { public static final short I2F = 134; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1839,7 +1923,7 @@ public final class Const { public static final short I2D = 135; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1847,7 +1931,7 @@ public final class Const { public static final short L2I = 136; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1855,7 +1939,7 @@ public final class Const { public static final short L2F = 137; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1863,7 +1947,7 @@ public final class Const { public static final short L2D = 138; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1871,7 +1955,7 @@ public final class Const { public static final short F2I = 139; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1879,7 +1963,7 @@ public final class Const { public static final short F2L = 140; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1887,7 +1971,7 @@ public final class Const { public static final short F2D = 141; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1895,7 +1979,7 @@ public final class Const { public static final short D2I = 142; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1903,7 +1987,7 @@ public final class Const { public static final short D2L = 143; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1911,7 +1995,7 @@ public final class Const { public static final short D2F = 144; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1919,7 +2003,7 @@ public final class Const { public static final short I2B = 145; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1927,7 +2011,7 @@ public final class Const { public static final short INT2BYTE = 145; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1935,7 +2019,7 @@ public final class Const { public static final short I2C = 146; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1943,7 +2027,7 @@ public final class Const { public static final short INT2CHAR = 146; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1951,7 +2035,7 @@ public final class Const { public static final short I2S = 147; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1959,7 +2043,7 @@ public final class Const { public static final short INT2SHORT = 147; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1967,7 +2051,7 @@ public final class Const { public static final short LCMP = 148; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1975,7 +2059,7 @@ public final class Const { public static final short FCMPL = 149; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1983,7 +2067,7 @@ public final class Const { public static final short FCMPG = 150; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1991,7 +2075,7 @@ public final class Const { public static final short DCMPL = 151; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1999,7 +2083,7 @@ public final class Const { public static final short DCMPG = 152; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2007,7 +2091,7 @@ public final class Const { public static final short IFEQ = 153; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2015,7 +2099,7 @@ public final class Const { public static final short IFNE = 154; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2023,7 +2107,7 @@ public final class Const { public static final short IFLT = 155; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2031,7 +2115,7 @@ public final class Const { public static final short IFGE = 156; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2039,7 +2123,7 @@ public final class Const { public static final short IFGT = 157; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2047,7 +2131,7 @@ public final class Const { public static final short IFLE = 158; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2055,7 +2139,7 @@ public final class Const { public static final short IF_ICMPEQ = 159; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2063,7 +2147,7 @@ public final class Const { public static final short IF_ICMPNE = 160; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2071,7 +2155,7 @@ public final class Const { public static final short IF_ICMPLT = 161; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2079,7 +2163,7 @@ public final class Const { public static final short IF_ICMPGE = 162; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2087,7 +2171,7 @@ public final class Const { public static final short IF_ICMPGT = 163; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2095,7 +2179,7 @@ public final class Const { public static final short IF_ICMPLE = 164; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2103,7 +2187,7 @@ public final class Const { public static final short IF_ACMPEQ = 165; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2111,7 +2195,7 @@ public final class Const { public static final short IF_ACMPNE = 166; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2119,7 +2203,7 @@ public final class Const { public static final short GOTO = 167; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2127,7 +2211,7 @@ public final class Const { public static final short JSR = 168; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2135,7 +2219,7 @@ public final class Const { public static final short RET = 169; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2143,7 +2227,7 @@ public final class Const { public static final short TABLESWITCH = 170; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2151,7 +2235,7 @@ public final class Const { public static final short LOOKUPSWITCH = 171; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2159,7 +2243,7 @@ public final class Const { public static final short IRETURN = 172; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2167,7 +2251,7 @@ public final class Const { public static final short LRETURN = 173; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2175,7 +2259,7 @@ public final class Const { public static final short FRETURN = 174; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2183,7 +2267,7 @@ public final class Const { public static final short DRETURN = 175; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2191,7 +2275,7 @@ public final class Const { public static final short ARETURN = 176; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2199,7 +2283,7 @@ public final class Const { public static final short RETURN = 177; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2207,7 +2291,7 @@ public final class Const { public static final short GETSTATIC = 178; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2215,7 +2299,7 @@ public final class Const { public static final short PUTSTATIC = 179; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2223,7 +2307,7 @@ public final class Const { public static final short GETFIELD = 180; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2231,7 +2315,7 @@ public final class Const { public static final short PUTFIELD = 181; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2239,7 +2323,7 @@ public final class Const { public static final short INVOKEVIRTUAL = 182; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2247,7 +2331,7 @@ public final class Const { public static final short INVOKESPECIAL = 183; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2255,7 +2339,7 @@ public final class Const { public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0 /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2263,7 +2347,7 @@ public final class Const { public static final short INVOKESTATIC = 184; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2271,7 +2355,7 @@ public final class Const { public static final short INVOKEINTERFACE = 185; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2279,7 +2363,7 @@ public final class Const { public static final short INVOKEDYNAMIC = 186; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2287,7 +2371,7 @@ public final class Const { public static final short NEW = 187; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2295,7 +2379,7 @@ public final class Const { public static final short NEWARRAY = 188; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2303,7 +2387,7 @@ public final class Const { public static final short ANEWARRAY = 189; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2311,7 +2395,7 @@ public final class Const { public static final short ARRAYLENGTH = 190; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2319,7 +2403,7 @@ public final class Const { public static final short ATHROW = 191; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2327,7 +2411,7 @@ public final class Const { public static final short CHECKCAST = 192; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2335,7 +2419,7 @@ public final class Const { public static final short INSTANCEOF = 193; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2343,7 +2427,7 @@ public final class Const { public static final short MONITORENTER = 194; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2351,7 +2435,7 @@ public final class Const { public static final short MONITOREXIT = 195; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2359,7 +2443,7 @@ public final class Const { public static final short WIDE = 196; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2367,7 +2451,7 @@ public final class Const { public static final short MULTIANEWARRAY = 197; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2375,7 +2459,7 @@ public final class Const { public static final short IFNULL = 198; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2383,7 +2467,7 @@ public final class Const { public static final short IFNONNULL = 199; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2391,7 +2475,7 @@ public final class Const { public static final short GOTO_W = 200; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2399,7 +2483,7 @@ public final class Const { public static final short JSR_W = 201; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2407,7 +2491,7 @@ public final class Const { public static final short BREAKPOINT = 202; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2418,7 +2502,7 @@ public final class Const { public static final short LDC_QUICK = 203; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2429,7 +2513,7 @@ public final class Const { public static final short LDC_W_QUICK = 204; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2440,7 +2524,7 @@ public final class Const { public static final short LDC2_W_QUICK = 205; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2451,7 +2535,7 @@ public final class Const { public static final short GETFIELD_QUICK = 206; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2462,7 +2546,7 @@ public final class Const { public static final short PUTFIELD_QUICK = 207; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2473,7 +2557,7 @@ public final class Const { public static final short GETFIELD2_QUICK = 208; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2484,7 +2568,7 @@ public final class Const { public static final short PUTFIELD2_QUICK = 209; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2495,7 +2579,7 @@ public final class Const { public static final short GETSTATIC_QUICK = 210; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2506,7 +2590,7 @@ public final class Const { public static final short PUTSTATIC_QUICK = 211; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2517,7 +2601,7 @@ public final class Const { public static final short GETSTATIC2_QUICK = 212; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2528,7 +2612,7 @@ public final class Const { public static final short PUTSTATIC2_QUICK = 213; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2539,7 +2623,7 @@ public final class Const { public static final short INVOKEVIRTUAL_QUICK = 214; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2550,7 +2634,7 @@ public final class Const { public static final short INVOKENONVIRTUAL_QUICK = 215; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2561,7 +2645,7 @@ public final class Const { public static final short INVOKESUPER_QUICK = 216; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2572,7 +2656,7 @@ public final class Const { public static final short INVOKESTATIC_QUICK = 217; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2583,7 +2667,7 @@ public final class Const { public static final short INVOKEINTERFACE_QUICK = 218; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2594,7 +2678,7 @@ public final class Const { public static final short INVOKEVIRTUALOBJECT_QUICK = 219; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2605,7 +2689,7 @@ public final class Const { public static final short NEW_QUICK = 221; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2616,7 +2700,7 @@ public final class Const { public static final short ANEWARRAY_QUICK = 222; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2627,7 +2711,7 @@ public final class Const { public static final short MULTIANEWARRAY_QUICK = 223; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2638,7 +2722,7 @@ public final class Const { public static final short CHECKCAST_QUICK = 224; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2649,7 +2733,7 @@ public final class Const { public static final short INSTANCEOF_QUICK = 225; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2660,7 +2744,7 @@ public final class Const { public static final short INVOKEVIRTUAL_QUICK_W = 226; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2671,7 +2755,7 @@ public final class Const { public static final short GETFIELD_QUICK_W = 227; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2682,7 +2766,7 @@ public final class Const { public static final short PUTFIELD_QUICK_W = 228; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2690,7 +2774,7 @@ public final class Const { public static final short IMPDEP1 = 254; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2698,34 +2782,44 @@ public final class Const { public static final short IMPDEP2 = 255; /** - * BCEL virtual instruction for pushing an arbitrary data type onto the stack. Will be converted to the appropriate JVM + * BCEL virtual instruction for pushing an arbitrary data type onto the stack: {@value}. Will be converted to the appropriate JVM * opcode when the class is dumped. */ public static final short PUSH = 4711; /** - * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH. Will be converted to the appropriate JVM opcode when + * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH: {@value}. Will be converted to the appropriate JVM opcode when * the class is dumped. */ public static final short SWITCH = 4712; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short UNDEFINED = -1; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short UNPREDICTABLE = -2; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short RESERVED = -3; - /** Mnemonic for an illegal opcode. */ + /** + * Mnemonic for an illegal opcode: {@value}. + */ public static final String ILLEGAL_OPCODE = ""; - /** Mnemonic for an illegal type. */ + /** + * Mnemonic for an illegal type: {@value}. + */ public static final String ILLEGAL_TYPE = ""; /** - * Boolean data type. + * Boolean data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2733,7 +2827,7 @@ public final class Const { public static final byte T_BOOLEAN = 4; /** - * Char data type. + * Char data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2741,7 +2835,7 @@ public final class Const { public static final byte T_CHAR = 5; /** - * Float data type. + * Float data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2749,7 +2843,7 @@ public final class Const { public static final byte T_FLOAT = 6; /** - * Double data type. + * Double data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2757,7 +2851,7 @@ public final class Const { public static final byte T_DOUBLE = 7; /** - * Byte data type. + * Byte data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2765,7 +2859,7 @@ public final class Const { public static final byte T_BYTE = 8; /** - * Short data type. + * Short data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2773,7 +2867,7 @@ public final class Const { public static final byte T_SHORT = 9; /** - * Int data type. + * Int data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2781,7 +2875,7 @@ public final class Const { public static final byte T_INT = 10; /** - * Long data type. + * Long data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2827,7 +2921,7 @@ public final class Const { /** * The signature characters corresponding to primitive types, e.g., SHORT_TYPE_NAMES[T_INT] = "I" */ - private static final String[] SHORT_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "Z", "C", "F", "D", "B", "S", "I", "J", "V", + public static final String[] SHORT_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "Z", "C", "F", "D", "B", "S", "I", "J", "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE}; /** @@ -3036,11 +3130,13 @@ public final class Const { public static final byte ATTR_MODULE_MAIN_CLASS = 24; public static final byte ATTR_NEST_HOST = 25; public static final byte ATTR_NEST_MEMBERS = 26; - public static final short KNOWN_ATTRIBUTES = 27; // count of attributes + public static final byte ATTR_RECORD = 27; + + public static final short KNOWN_ATTRIBUTES = 28; // count of attributes private static final String[] ATTRIBUTE_NAMES = {"SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable", "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap", "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", - "StackMapTable", "BootstrapMethods", "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers"}; + "StackMapTable", "BootstrapMethods", "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers", "Record"}; /** * Constants used in the StackMap attribute. */ @@ -3070,6 +3166,7 @@ public final class Const { public static final int SAME_FRAME_EXTENDED = 251; public static final int APPEND_FRAME = 252; public static final int FULL_FRAME = 255; + /** * Constants that define the maximum value of those constants which store ranges. */ @@ -3090,6 +3187,7 @@ public final class Const { public static final byte REF_invokeSpecial = 7; public static final byte REF_newInvokeSpecial = 8; public static final byte REF_invokeInterface = 9; + /** * The names of the reference_kinds of a CONSTANT_MethodHandle_info. */ @@ -3097,7 +3195,7 @@ public final class Const { "newInvokeSpecial", "invokeInterface"}; /** - * @param index + * @param index index into {@code ACCESS_NAMES}. * @return the ACCESS_NAMES entry at the given index * @since 6.0 */ @@ -3107,7 +3205,7 @@ public static String getAccessName(final int index) { /** * - * @param index + * @param index index into {@code ACCESS_NAMES}. * @return the attribute name * @since 6.0 */ @@ -3118,7 +3216,7 @@ public static String getAttributeName(final int index) { /** * The primitive class names corresponding to the T_XX constants, e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer" * - * @param index + * @param index index into {@code CLASS_TYPE_NAMES}. * @return the class name * @since 6.0 */ @@ -3128,7 +3226,7 @@ public static String getClassTypeName(final int index) { /** * - * @param index + * @param index index into {@code CONSTANT_NAMES}. * @return the CONSTANT_NAMES entry at the given index * @since 6.0 */ @@ -3140,7 +3238,7 @@ public static String getConstantName(final int index) { /** * - * @param index + * @param index index into {@code CONSUME_STACK}. * @return Number of words consumed on operand stack * @since 6.0 */ @@ -3157,7 +3255,7 @@ public static Iterable getInterfacesImplementedByArrays() { /** * - * @param index + * @param index index into {@code ITEM_NAMES}. * @return the item name * @since 6.0 */ @@ -3167,7 +3265,7 @@ public static String getItemName(final int index) { /** * - * @param index + * @param index index into {@code METHODHANDLE_NAMES}. * @return the method handle name * @since 6.0 */ @@ -3177,7 +3275,7 @@ public static String getMethodHandleName(final int index) { /** * - * @param index + * @param index index into {@code NO_OF_OPERANDS}. * @return Number of byte code operands * @since 6.0 */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java index d45c5794b7ba..89cf3f835daf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.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 @@ -26,7 +26,7 @@ * Exception constants. * * @since 6.0 (intended to replace the InstructionConstant interface) - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ExceptionConst { @@ -52,7 +52,6 @@ public enum EXCS { * Super class of any linking exception (aka Linkage Error) */ public static final Class LINKING_EXCEPTION = LinkageError.class; - /** * Linking Exceptions */ @@ -67,10 +66,10 @@ public enum EXCS { public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class; public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class; public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class; + public static final Class VERIFY_ERROR = VerifyError.class; /* UnsupportedClassVersionError is new in JDK 1.2 */ // public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class; - /** * Run-Time Exceptions */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java index d36260cc23ad..10f6a1a8ff43 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/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 @@ -30,7 +30,7 @@ * @see com.sun.org.apache.bcel.internal.util.Repository * @see SyntheticRepository * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public abstract class Repository { @@ -174,7 +174,7 @@ public static JavaClass lookupClass(final Class clazz) throws ClassNotFoundEx } /** - * Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it. + * Lookups class somewhere found on your CLASSPATH, or whereever the repository instance looks for it. * * @return class object for given fully qualified class name * @throws ClassNotFoundException if the class could not be found or parsed correctly diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java index 61ec9c4d6909..f1d350894c9b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.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 @@ -25,27 +25,36 @@ * Super class for all objects that have modifiers like private, final, ... I.e. * classes, fields, and methods. * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class AccessFlags { /** - * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + * Access flags. + * + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. */ @java.lang.Deprecated protected int access_flags; // TODO not used externally at present + /** + * Constructs a new instance. + */ public AccessFlags() { } /** - * @param a initial access flags + * Constructs a new instance. + * + * @param accessFlags initial access flags. */ - public AccessFlags(final int a) { - access_flags = a; + public AccessFlags(final int accessFlags) { + access_flags = accessFlags; } /** + * Gets access flags. + * * @return Access flags of the object aka. "modifiers". */ public final int getAccessFlags() { @@ -53,142 +62,303 @@ public final int getAccessFlags() { } /** - * @return Access flags of the object aka. "modifiers". + * Gets access flags. + * + * @return Access flags of the object also known as modifiers. */ public final int getModifiers() { return access_flags; } + /** + * Tests whether the abstract bit is on. + * + * @return whether the abstract bit is on. + */ public final boolean isAbstract() { - return (access_flags & Const.ACC_ABSTRACT) != 0; + return test(Const.ACC_ABSTRACT); } + /** + * Sets the abstract bit. + * + * @param flag The new value. + */ public final void isAbstract(final boolean flag) { setFlag(Const.ACC_ABSTRACT, flag); } + /** + * Tests whether the annotation bit is on. + * + * @return whether the annotation bit is on. + */ public final boolean isAnnotation() { - return (access_flags & Const.ACC_ANNOTATION) != 0; + return test(Const.ACC_ANNOTATION); } + /** + * Sets the annotation bit. + * + * @param flag The new value. + */ public final void isAnnotation(final boolean flag) { setFlag(Const.ACC_ANNOTATION, flag); } - + /** + * Tests whether the enum bit is on. + * + * @return whether the enum bit is on. + */ public final boolean isEnum() { - return (access_flags & Const.ACC_ENUM) != 0; + return test(Const.ACC_ENUM); } + /** + * Sets the enum bit. + * + * @param flag The new value. + */ public final void isEnum(final boolean flag) { setFlag(Const.ACC_ENUM, flag); } + /** + * Tests whether the final bit is on. + * + * @return whether the final bit is on. + */ public final boolean isFinal() { - return (access_flags & Const.ACC_FINAL) != 0; + return test(Const.ACC_FINAL); } + /** + * Sets the final bit. + * + * @param flag The new value. + */ public final void isFinal(final boolean flag) { setFlag(Const.ACC_FINAL, flag); } + /** + * Tests whether the interface bit is on. + * + * @return whether the interface bit is on. + */ public final boolean isInterface() { - return (access_flags & Const.ACC_INTERFACE) != 0; + return test(Const.ACC_INTERFACE); } + /** + * Sets the interface bit. + * + * @param flag The new value. + */ public final void isInterface(final boolean flag) { setFlag(Const.ACC_INTERFACE, flag); } + /** + * Tests whether the native bit is on. + * + * @return whether the native bit is on. + */ public final boolean isNative() { - return (access_flags & Const.ACC_NATIVE) != 0; + return test(Const.ACC_NATIVE); } + /** + * Sets the native bit. + * + * @param flag The new value. + */ public final void isNative(final boolean flag) { setFlag(Const.ACC_NATIVE, flag); } + /** + * Tests whether the private bit is on. + * + * @return whether the private bit is on. + */ public final boolean isPrivate() { - return (access_flags & Const.ACC_PRIVATE) != 0; + return test(Const.ACC_PRIVATE); } + /** + * Sets the private bit. + * + * @param flag The new value. + */ public final void isPrivate(final boolean flag) { setFlag(Const.ACC_PRIVATE, flag); } + /** + * Tests whether the protected bit is on. + * + * @return whether the protected bit is on. + */ public final boolean isProtected() { - return (access_flags & Const.ACC_PROTECTED) != 0; + return test(Const.ACC_PROTECTED); } + /** + * Sets the protected bit. + * + * @param flag The new value. + */ public final void isProtected(final boolean flag) { setFlag(Const.ACC_PROTECTED, flag); } + /** + * Tests whether the public bit is on. + * + * @return whether the public bit is on. + */ public final boolean isPublic() { - return (access_flags & Const.ACC_PUBLIC) != 0; + return test(Const.ACC_PUBLIC); } + /** + * Sets the public bit. + * + * @param flag The new value. + */ public final void isPublic(final boolean flag) { setFlag(Const.ACC_PUBLIC, flag); } + /** + * Tests whether the static bit is on. + * + * @return whether the static bit is on. + */ public final boolean isStatic() { - return (access_flags & Const.ACC_STATIC) != 0; + return test(Const.ACC_STATIC); } + /** + * Sets the static bit. + * + * @param flag The new value. + */ public final void isStatic(final boolean flag) { setFlag(Const.ACC_STATIC, flag); } + /** + * Tests whether the strict bit is on. + * + * @return whether the strict bit is on. + */ public final boolean isStrictfp() { - return (access_flags & Const.ACC_STRICT) != 0; + return test(Const.ACC_STRICT); } + /** + * Sets the strict bit. + * + * @param flag The new value. + */ public final void isStrictfp(final boolean flag) { setFlag(Const.ACC_STRICT, flag); } + /** + * Tests whether the synchronized bit is on. + * + * @return whether the synchronized bit is on. + */ public final boolean isSynchronized() { - return (access_flags & Const.ACC_SYNCHRONIZED) != 0; + return test(Const.ACC_SYNCHRONIZED); } + /** + * Sets the synchronized bit. + * + * @param flag The new value. + */ public final void isSynchronized(final boolean flag) { setFlag(Const.ACC_SYNCHRONIZED, flag); } + /** + * Tests whether the synthetic bit is on. + * + * @return whether the synthetic bit is on. + */ public final boolean isSynthetic() { - return (access_flags & Const.ACC_SYNTHETIC) != 0; + return test(Const.ACC_SYNTHETIC); } + /** + * Sets the synthetic bit. + * + * @param flag The new value. + */ public final void isSynthetic(final boolean flag) { setFlag(Const.ACC_SYNTHETIC, flag); } + /** + * Tests whether the transient bit is on. + * + * @return whether the varargs bit is on. + */ public final boolean isTransient() { - return (access_flags & Const.ACC_TRANSIENT) != 0; + return test(Const.ACC_TRANSIENT); } + /** + * Sets the varargs bit. + * + * @param flag The new value. + */ public final void isTransient(final boolean flag) { setFlag(Const.ACC_TRANSIENT, flag); } + /** + * Tests whether the varargs bit is on. + * + * @return whether the varargs bit is on. + */ public final boolean isVarArgs() { - return (access_flags & Const.ACC_VARARGS) != 0; + return test(Const.ACC_VARARGS); } + /** + * Sets the varargs bit. + * + * @param flag The new value. + */ public final void isVarArgs(final boolean flag) { setFlag(Const.ACC_VARARGS, flag); } + /** + * Tests whether the volatile bit is on. + * + * @return whether the volatile bit is on. + */ public final boolean isVolatile() { - return (access_flags & Const.ACC_VOLATILE) != 0; + return test(Const.ACC_VOLATILE); } + /** + * Sets the volatile bit. + * + * @param flag The new value. + */ public final void isVolatile(final boolean flag) { setFlag(Const.ACC_VOLATILE, flag); } /** - * Set access flags aka "modifiers". + * Sets access flags also known as modifiers. * * @param accessFlags Access flags of the object. */ @@ -207,11 +377,21 @@ private void setFlag(final int flag, final boolean set) { } /** - * Set access flags aka "modifiers". + * Sets access flags aka "modifiers". * * @param accessFlags Access flags of the object. */ public final void setModifiers(final int accessFlags) { setAccessFlags(accessFlags); } + + /** + * Tests whether the bit is on. + * + * @param test the bit to test. + * @return whether the bit is on. + */ + private boolean test(final short test) { + return (access_flags & test) != 0; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java index 466e9bf3404a..c9503332a6f4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,20 +26,22 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; +import jdk.xml.internal.Utils; /** * Represents one annotation in the annotation table * * @since 6.0 + * @LastModified: Sept 2025 */ public class AnnotationEntry implements Node { public static final AnnotationEntry[] EMPTY_ARRAY = {}; - public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) { + public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attributes) { // Find attributes that contain annotation data - return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries())) - .toArray(AnnotationEntry[]::new); + return Utils.streamOfIfNonNull(attributes).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries())) + .toArray(AnnotationEntry[]::new); } /** @@ -55,7 +56,6 @@ public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException { final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible); final int numElementValuePairs = input.readUnsignedShort(); - annotationEntry.elementValuePairs = new ArrayList<>(); for (int i = 0; i < numElementValuePairs; i++) { annotationEntry.elementValuePairs .add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool)); @@ -69,12 +69,13 @@ public static AnnotationEntry read(final DataInput input, final ConstantPool con private final boolean isRuntimeVisible; - private List elementValuePairs; + private final List elementValuePairs; public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) { this.typeIndex = typeIndex; this.constantPool = constantPool; this.isRuntimeVisible = isRuntimeVisible; + this.elementValuePairs = new ArrayList<>(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java index 52ac9d0dd98d..6ff9b4a046f0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java @@ -52,7 +52,7 @@ public abstract class Annotations extends Attribute implements Iterable iterator() { * @param annotationTable the entries to set in this annotation */ public final void setAnnotationTable(final AnnotationEntry[] annotationTable) { - this.annotationTable = annotationTable; + this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY; } /** @@ -151,9 +148,6 @@ public final String toString() { } protected void writeAnnotations(final DataOutputStream dos) throws IOException { - if (annotationTable == null) { - return; - } dos.writeShort(annotationTable.length); for (final AnnotationEntry element : annotationTable) { element.dump(dos); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java index e8768886de5e..35d0412f57a1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java @@ -31,12 +31,12 @@ public class ArrayElementValue extends ElementValue { // For array types, this is the array private final ElementValue[] elementValues; - public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool) { + public ArrayElementValue(final int type, final ElementValue[] elementValues, final ConstantPool cpool) { super(type, cpool); if (type != ARRAY) { throw new ClassFormatException("Only element values of type array can be built with this ctor - type specified: " + type); } - this.elementValues = datums; + this.elementValues = elementValues != null ? elementValues : EMPTY_ARRAY; } @Override diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java index bf72fee4e001..cd03615cbc0f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.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 @@ * @see Synthetic * @see Deprecated * @see Signature - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public abstract class Attribute implements Cloneable, Node { private static final boolean debug = false; @@ -181,6 +181,8 @@ public static Attribute readAttribute(final DataInput dataInput, final ConstantP return new NestHost(nameIndex, length, dataInput, constantPool); case Const.ATTR_NEST_MEMBERS: return new NestMembers(nameIndex, length, dataInput, constantPool); + case Const.ATTR_RECORD: + return new Record(nameIndex, length, dataInput, constantPool); default: // Never reached throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); @@ -279,7 +281,7 @@ public Object clone() { try { attr = (Attribute) super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } return attr; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java index 61b818ec4f03..224e0df6b940 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +26,7 @@ import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import jdk.xml.internal.Utils; /** * This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments @@ -35,9 +35,12 @@ * @see The class File Format : * The BootstrapMethods Attribute * @since 6.0 + * @LastModified: Sept 2025 */ public class BootstrapMethod implements Cloneable { + static final BootstrapMethod[] EMPTY_ARRAY = {}; + /** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */ private int bootstrapMethodRef; @@ -54,7 +57,7 @@ public BootstrapMethod(final BootstrapMethod c) { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param input Input stream * @throws IOException if an I/O error occurs. @@ -78,7 +81,7 @@ private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArgu */ public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) { this.bootstrapMethodRef = bootstrapMethodRef; - this.bootstrapArguments = bootstrapArguments; + setBootstrapArguments(bootstrapArguments); } /** @@ -87,7 +90,7 @@ public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArgume public BootstrapMethod copy() { try { return (BootstrapMethod) clone(); - } catch (final CloneNotSupportedException e) { + } catch (final CloneNotSupportedException ignore) { // TODO should this throw? } return null; @@ -132,7 +135,7 @@ public int getNumBootstrapArguments() { * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info */ public void setBootstrapArguments(final int[] bootstrapArguments) { - this.bootstrapArguments = bootstrapArguments; + this.bootstrapArguments = Utils.createEmptyArrayIfNull(bootstrapArguments); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java index 6f9930f1b164..ef2475e18569 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java @@ -58,11 +58,11 @@ public BootstrapMethods(final BootstrapMethods c) { */ public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) { super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool); - this.bootstrapMethods = bootstrapMethods; + setBootstrapMethods(bootstrapMethods); } /** - * 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 @@ -135,7 +135,7 @@ public Iterator iterator() { * @param bootstrapMethods the array of bootstrap methods */ public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) { - this.bootstrapMethods = bootstrapMethods; + this.bootstrapMethods = bootstrapMethods != null ? bootstrapMethods : BootstrapMethod.EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java index a61e1d75390b..037f3908379e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java @@ -47,12 +47,10 @@ public ClassFormatException(final String message) { /** * Constructs a new instance with the specified detail message and cause. - *

- * Note that the detail message associated with {@code cause} is not automatically incorporated in this runtime exception's detail message. * * @param message the detail message (which 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.) + * @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. * @since 6.0 */ public ClassFormatException(final String message, final Throwable cause) { @@ -63,8 +61,8 @@ public ClassFormatException(final String message, final Throwable cause) { * Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the * class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables. * - * @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.) + * @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. * @since 6.7.0 */ public ClassFormatException(final Throwable cause) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java index c9daaeabf9b1..0dbda722ec49 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java @@ -37,7 +37,7 @@ * appropriate exception is propagated back to the caller. * * The structure and the names comply, except for a few conveniences, exactly with the - * JVM specification 1.0. See this paper for further details about + * JVM specification 1.0. See this paper for further details about * the structure of a bytecode file. */ public final class ClassParser { @@ -57,7 +57,7 @@ public final class ClassParser { private Field[] fields; // class fields, i.e., its variables private Method[] methods; // methods defined in the class private Attribute[] attributes; // attributes defined in the class - private final boolean isZip; // Loaded from zip file + private final boolean isZip; // Loaded from ZIP file /** * Parses class from the given stream. @@ -91,7 +91,7 @@ public ClassParser(final String fileName) { /** * Parses class from given .class file in a ZIP-archive * - * @param zipFile zip file name + * @param zipFile ZIP file name * @param fileName file name */ public ClassParser(final String zipFile, final String fileName) { @@ -104,7 +104,7 @@ public ClassParser(final String zipFile, final String fileName) { /** * Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods, * fields and commands. A ClassFormatException is raised, if the file is not a valid .class file. (This does - * not include verification of the byte code as it is performed by the java interpreter). + * not include verification of the byte code as it is performed by the Java interpreter). * * @return Class object representing the parsed class file * @throws IOException if an I/O error occurs. @@ -151,11 +151,11 @@ public JavaClass parse() throws IOException, ClassFormatException { // for (int i=0; i < u.length; i++) // System.err.println("WARNING: " + u[i]); // Everything should have been read now - // if(file.available() > 0) { + // if (file.available() > 0) { // int bytes = file.available(); // byte[] buf = new byte[bytes]; // file.read(buf); - // if(!(isZip && (buf.length == 1))) { + // if (!(isZip && (buf.length == 1))) { // System.err.println("WARNING: Trailing garbage at end of " + fileName); // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); // } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java index 498a8c71b186..7573a5412e73 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.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 a chunk of Java byte code contained in a method. It is instantiated by the @@ -59,7 +60,7 @@ * @see CodeException * @see LineNumberTable * @see LocalVariableTable - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class Code extends Attribute { @@ -93,7 +94,7 @@ public Code(final Code code) { code = new byte[codeLength]; // Read byte code file.readFully(code); /* - * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch() + * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch () * block. */ final int exceptionTableLength = file.readUnsignedShort(); @@ -107,7 +108,7 @@ public Code(final Code code) { final int attributesCount = file.readUnsignedShort(); attributes = new Attribute[attributesCount]; for (int i = 0; i < attributesCount; i++) { - attributes[i] = Attribute.readAttribute(file, constantPool); + attributes[i] = readAttribute(file, constantPool); } /* * Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal @@ -131,8 +132,8 @@ public Code(final int nameIndex, final int length, final int maxStack, final int super(Const.ATTR_CODE, nameIndex, length, constantPool); this.maxStack = Args.requireU2(maxStack, "maxStack"); this.maxLocals = Args.requireU2(maxLocals, "maxLocals"); - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); + this.exceptionTable = Utils.createEmptyArrayIfNull(exceptionTable, CodeException[].class); Args.requireU2(this.exceptionTable.length, "exceptionTable.length"); this.attributes = attributes != null ? attributes : EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length @@ -263,6 +264,20 @@ public LocalVariableTable getLocalVariableTable() { return null; } + /** + * Gets the local variable type table attribute {@link LocalVariableTypeTable}. + * @return LocalVariableTypeTable of Code, if it has one, null otherwise. + * @since 6.10.0 + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + for (final Attribute attribute : attributes) { + if (attribute instanceof LocalVariableTypeTable) { + return (LocalVariableTypeTable) attribute; + } + } + return null; + } + /** * @return Number of local variables. */ @@ -277,6 +292,20 @@ public int getMaxStack() { return maxStack; } + /** + * Finds the attribute of {@link StackMap} instance. + * @return StackMap of Code, if it has one, else null. + * @since 6.8.0 + */ + public StackMap getStackMap() { + for (final Attribute attribute : attributes) { + if (attribute instanceof StackMap) { + return (StackMap) attribute; + } + } + return null; + } + /** * @param attributes the attributes to set for this Code */ @@ -289,7 +318,7 @@ public void setAttributes(final Attribute[] attributes) { * @param code byte code */ public void setCode(final byte[] code) { - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); super.setLength(calculateLength()); // Adjust length } @@ -297,7 +326,7 @@ public void setCode(final byte[] code) { * @param exceptionTable exception table */ public void setExceptionTable(final CodeException[] exceptionTable) { - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java index ee224e6b348e..b8bf109239ee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.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 @@ -52,19 +52,19 @@ * * * @see Code - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class CodeException implements Cloneable, Node { /** * Empty array. */ - static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {}; + static final CodeException[] EMPTY_ARRAY = {}; /** Range in the code the exception handler. */ private int startPc; - /** active. startPc is inclusive, endPc exclusive. */ + /** Active. startPc is inclusive, endPc exclusive. */ private int endPc; /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java index 885e1b599eb5..9b3d6f31e171 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.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 @@ -32,30 +32,29 @@ * in the constant pool of a class file. The classes keep closely to * the JVM specification. * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Constant implements Cloneable, Node { - private static BCELComparator bcelComparator = new BCELComparator() { + static final Constant[] EMPTY_ARRAY = {}; + + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Constant THIS = (Constant) o1; - final Constant THAT = (Constant) o2; - return Objects.equals(THIS.toString(), THAT.toString()); + public boolean equals(final Constant a, final Constant b) { + return a == b || a != null && b != null && Objects.equals(a.toString(), b.toString()); } @Override - public int hashCode(final Object o) { - final Constant THIS = (Constant) o; - return THIS.toString().hashCode(); + public int hashCode(final Constant o) { + return o != null ? Objects.hashCode(o.toString()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -113,7 +112,7 @@ public static Constant readConstant(final DataInput dataInput) throws IOExceptio /** * @param comparator Comparison strategy object */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -148,7 +147,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 } } @@ -174,7 +173,7 @@ public Constant copy() { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Constant && bcelComparator.equals(this, (Constant) obj); } /** @@ -185,7 +184,7 @@ public final byte getTag() { } /** - * Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of + * Returns value as defined by given BCELComparator strategy. By default return the hash code of the result of * toString(). * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java index 71fd91b249a5..51113a1aeaa2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 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,11 +28,11 @@ /** * Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants. * - * @see ConstantFieldref - * @see ConstantMethodref - * @see ConstantInterfaceMethodref - * @see ConstantInvokeDynamic - * @LastModified: Jun 2019 + * @see ConstantFieldref + * @see ConstantMethodref + * @see ConstantInterfaceMethodref + * @see ConstantInvokeDynamic + * @LastModified: Sept 2025 */ public abstract class ConstantCP extends Constant { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java index ebb3d0af46a4..14b43937c929 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 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,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a Double object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantDouble extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java index 9c30c9e4fdb4..e86bbb94e662 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 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,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a float object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantFloat extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java index cabd2e15b035..20c0717acb6d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 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,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to an int object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantInteger extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java index c1e683abadb4..6936162c2642 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.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 @@ -29,8 +29,8 @@ /** * This class is derived from the abstract {@link Constant} and represents a reference to a long object. * - * @see Constant - * @LastModified: Jan 2020 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantLong extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java index cb28f7dacb8d..ab187b7e4f89 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java @@ -29,7 +29,10 @@ public interface ConstantObject { /** - * @return object representing the constant, e.g., Long for ConstantLong + * Gets the object representing the constant, e.g., Long for ConstantLong. + * + * @param constantPool the constant. + * @return object representing the constant, e.g., Long for ConstantLong. */ - Object getConstantValue(ConstantPool cp); + Object getConstantValue(ConstantPool constantPool); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java index 5fb4ef1b0808..ae1e3977c99b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,7 +35,7 @@ * * @see Constant * @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ConstantPool implements Cloneable, Node, Iterable { @@ -73,7 +73,7 @@ private static String escape(final String str) { * @param constantPool Array of constants */ public ConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + setConstantPool(constantPool); } /** @@ -88,6 +88,7 @@ public ConstantPool(final DataInput input) throws IOException { constantPool = new Constant[constantPoolCount]; /* * constantPool[0] is unused by the compiler and may be used freely by the implementation. + * constantPool[0] is currently unused by the implementation. */ for (int i = 1; i < constantPoolCount; i++) { constantPool[i] = Constant.readConstant(input); @@ -288,7 +289,7 @@ public T getConstant(final int index, final byte tag) throw */ public T getConstant(final int index, final byte tag, final Class castTo) throws ClassFormatException { final T c = getConstant(index); - if (c.getTag() != tag) { + if (c == null || c.getTag() != tag) { throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c); } return c; @@ -313,16 +314,18 @@ public T getConstant(final int index, final Class castTo throw new ClassFormatException("Invalid constant pool reference at index: " + index + ". Expected " + castTo + " but was " + constantPool[index].getClass()); } - // Previous check ensures this won't throw a ClassCastException - final T c = castTo.cast(constantPool[index]); - if (c == null - // the 0th element is always null - && index != 0) { + if (index > 1) { final Constant prev = constantPool[index - 1]; - if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) { - throw new ClassFormatException("Constant pool at index " + index + " is null."); + if (prev != null && (prev.getTag() == Const.CONSTANT_Double || prev.getTag() == Const.CONSTANT_Long)) { + throw new ClassFormatException("Constant pool at index " + index + " is invalid. The index is unused due to the preceeding " + + Const.getConstantName(prev.getTag()) + "."); } } + // Previous check ensures this won't throw a ClassCastException + final T c = castTo.cast(constantPool[index]); + if (c == null) { + throw new ClassFormatException("Constant pool at index " + index + " is null."); + } return c; } @@ -402,7 +405,7 @@ public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException * @return Length of constant pool. */ public int getLength() { - return constantPool == null ? 0 : constantPool.length; + return constantPool.length; } @Override @@ -421,7 +424,7 @@ public void setConstant(final int index, final Constant constant) { * @param constantPool */ public void setConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + this.constantPool = constantPool != null ? constantPool : Constant.EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java index ec875554c1af..90e45c807e5b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.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 @@ -36,11 +36,11 @@ * The following system properties govern caching this class performs. *

*
    - *
  • {@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 311e9a33fa31..143c2a255448 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 90841d96081f..c561afe33c53 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 3c475891acd9..934b608d6ac7 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 5c3d9b3172b6..d87307c0e7db 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 826ba41af70f..db33c8716569 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 90eaa3eb0629..1b6004b37409 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 7e6ccb2ecb59..8ffc796a0eaf 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 1daa6a62fd54..679d5a9eb7cb 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 d77582815b7b..82900dcca10a 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 2295ca5c625c..b61be1effa0c 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 000000000000..eaf1da2d2e13 --- /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 d6c4cfa6a07a..1b0e2ed1ce0a 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 4380d04bc06a..dc41ad065f84 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 6251fc514cca..96541f309bd2 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 fd56e14a539b..26fde9bdbdff 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 08868a82de8b..ce327e20f523 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 ba2623eec082..643c820f3661 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 ffc1a20f80a1..865e154d334a 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 5b5d1d77f6fe..2f5bffd8d3c8 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 00eebe18245e..addf6f0aea3b 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 8a97f4b6d084..f92f508b8629 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 a6ffd8828622..b73bd01f7942 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 06b404df72b7..388370a45e7e 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 96367e02d2da..f48587e5455d 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 f6c6058dfbbb..490e9cd5d442 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 c9c26c206495..3149a18290b3 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 05d982ca6e81..261f57d98a8f 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 c0395732d79f..792ef31cb723 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 9b1dd4c7b41f..b7b5e1f1d992 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 a3070fa7e0c9..6ebe60c8049b 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 4817793120ff..1e056b5d4f83 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 000000000000..f59cfa37ca4f --- /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 000000000000..3679647d4097 --- /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 7afb87195591..7a7c539f15ad 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 e4c3276f968b..3d50ce16d408 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 c91c77387b91..4bf8e6f71976 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 7e5d7eaaca3a..ab5355235f66 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 4f5d3a341b3a..2161bbcb6ecf 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 5e4e98d94df3..e3e1cf400315 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 e9ceed219579..bfa9cbf8fcb2 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 1f8ce5ea410b..317638e6b2d0 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 110e30392ab6..015083dd066f 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 4575b31dfce7..b93066d53b71 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 3683fd6437e7..c7fef8fcebc0 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 12dbbe4828a0..6967dcefd94b 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 74cb8400d3e7..1f6fe9c96eec 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 000000000000..4e8d383bcab6
--- /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 2d7188e9174f..db756700085d 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 bb2e953f8504..07171fefde15 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 ea01a8371750..0fad6ea7389d 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 71374877efeb..59b774a9afc3 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 138999ebe907..78a676e875ed 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 91ab9ac5463b..f489f9a76581 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 1dfd244141a8..ff45e5cde93e 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 1c1c032dbd53..8e024eebaa48 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 acaf45195676..debf930fe90b 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 fa660954d151..2518131cceea 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 bdc9c517a860..878f392b6b77 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 95ac794f2d7d..95c00ed38132 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 86a0cad256c4..2a488c85edeb 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 9d1f4d41d93a..30786370d290 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 6555392e9d46..bc1fbc8627e2 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 1c646f482923..87ba4cb913ea 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 5effd7edcd92..b3eb14a9ddf2 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 2865a158de26..998d072e0673 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 16c8e2444b43..a7124409f124 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 439268e35eb2..7b95bfc99b17 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 5e9220354c30..3c4b3e9f9da6 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 5e962354d162..2c94b770265a 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 7ffc3a8228ed..579efc9fe3b8 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 5146408ef490..0681476b5eec 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 c517b492f0a7..188ac95f6efe 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 @@ *
  * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
  * 
- * */ 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 d95bade23bd6..13ca0a84cfa8 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 3773c21e7b3c..68bb2abf5132 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 830564d42c90..71cfa0cf1c21 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 67184c0b9f14..f952a65880bb 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 f6e8333be798..be09b0a51591 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 46378a1b71ee..622a3cdd9615 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 a7cacc7c165c..99a1efbed166 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 fe75792e213a..9b94a1dcf2d4 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 aed1626ec0d8..f929176c1749 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 a90e795e99f4..a3086ac16642 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 a4de20315d72..363b3237632c 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 40ed6ff4c38e..038bbe631481 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: *

* - *
+ * 
  *     ...
  *     try {
  *         il.delete(start_ih, end_ih);
- *     } catch(TargetLostException e) {
+ *     } catch (TargetLostException e) {
  *         for (InstructionHandle target : e.getTargets()) {
  *             for (InstructionTargeter targeter : target.getTargeters()) {
  *                 targeter.updateTarget(target, new_target);
  *             }
  *         }
  *     }
- * 
+ *
* * @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 ea20710af2eb..b58645b402e9 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 5a22942a6a77..27b952f3996e 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 000000000000..63d4dc876cea --- /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 000000000000..581037d7981b --- /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 2e663bfdaa15..fb32dc35e0b0 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 c931fb1e4224..93f22e7d0add 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 151083ea71be..0eb9bfb4ee1a 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 f644c698b729..10d31974d47a 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 178ccc786b15..e95e8fbd0a0e 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 723fc07509b0..1935d724b3b9 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 5b045bf08cc9..510fe4a03a66 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 8d1ddf493cd4..c44e36d0a81f 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 000000000000..2bd92f155bcd --- /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 439930be15db..ba857e8cc07c 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, 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,7 +25,10 @@ package jdk.xml.internal; +import java.lang.reflect.Array; import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Stream; /** * General utility. Use JdkXmlUtils for XML processing related functions. @@ -54,4 +57,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 2c673d6b1af3..b64fc3640d4a 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.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java
index 81d4fd259ed0..3952ccd8d958 100644
--- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java
+++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java
@@ -28,12 +28,16 @@
 import com.sun.tools.attach.AttachNotSupportedException;
 import com.sun.tools.attach.spi.AttachProvider;
 
-import java.io.InputStream;
-import java.io.IOException;
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.nio.file.Files;
+
+import java.util.Optional;
+
+import java.util.regex.Pattern;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
@@ -46,13 +50,18 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
     // location is the same for all processes, otherwise the tools
     // will not be able to find all Hotspot processes.
     // Any changes to this needs to be synchronized with HotSpot.
-    private static final String tmpdir = "/tmp";
+    private static final Path TMPDIR = Path.of("/tmp");
+
+    private static final Path PROC     = Path.of("/proc");
+    private static final Path STATUS   = Path.of("status");
+    private static final Path ROOT_TMP = Path.of("root/tmp");
+
     String socket_path;
+
     /**
      * Attaches to the target VM
      */
-    VirtualMachineImpl(AttachProvider provider, String vmid)
-        throws AttachNotSupportedException, IOException
+    VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException
     {
         super(provider, vmid);
 
@@ -63,23 +72,26 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
         }
 
         // Try to resolve to the "inner most" pid namespace
-        int ns_pid = getNamespacePid(pid);
+        final long ns_pid = getNamespacePid(pid);
 
         // Find the socket file. If not found then we attempt to start the
         // attach mechanism in the target VM by sending it a QUIT signal.
         // Then we attempt to find the socket file again.
-        File socket_file = findSocketFile(pid, ns_pid);
+        final File socket_file = findSocketFile(pid, ns_pid);
         socket_path = socket_file.getPath();
         if (!socket_file.exists()) {
             // Keep canonical version of File, to delete, in case target process ends and /proc link has gone:
             File f = createAttachFile(pid, ns_pid).getCanonicalFile();
+
+            boolean timedout = false;
+
             try {
-                sendQuitTo(pid);
+                checkCatchesAndSendQuitTo(pid, false);
 
                 // give the target VM time to start the attach mechanism
                 final int delay_step = 100;
                 final long timeout = attachTimeout();
-                long time_spend = 0;
+                long time_spent = 0;
                 long delay = 0;
                 do {
                     // Increase timeout on each attempt to reduce polling
@@ -88,18 +100,19 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine {
                         Thread.sleep(delay);
                     } catch (InterruptedException x) { }
 
-                    time_spend += delay;
-                    if (time_spend > timeout/2 && !socket_file.exists()) {
+                    timedout = (time_spent += delay) > timeout;
+
+                    if (time_spent > timeout/2 && !socket_file.exists()) {
                         // Send QUIT again to give target VM the last chance to react
-                        sendQuitTo(pid);
+                        checkCatchesAndSendQuitTo(pid, !timedout);
                     }
-                } while (time_spend <= timeout && !socket_file.exists());
+                } while (!timedout && !socket_file.exists());
+
                 if (!socket_file.exists()) {
                     throw new AttachNotSupportedException(
                         String.format("Unable to open socket file %s: " +
                           "target process %d doesn't respond within %dms " +
-                          "or HotSpot VM not loaded", socket_path, pid,
-                                      time_spend));
+                          "or HotSpot VM not loaded", socket_path, pid, time_spent));
                 }
             } finally {
                 f.delete();
@@ -210,49 +223,55 @@ protected void close(long fd) throws IOException {
     }
 
     // Return the socket file for the given process.
-    private File findSocketFile(int pid, int ns_pid) throws IOException {
-        String root = findTargetProcessTmpDirectory(pid, ns_pid);
-        return new File(root, ".java_pid" + ns_pid);
+    private File findSocketFile(long pid, long ns_pid) throws AttachNotSupportedException, IOException {
+        return new File(findTargetProcessTmpDirectory(pid, ns_pid), ".java_pid" + ns_pid);
     }
 
     // On Linux a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid file in the
     // target VM's working directory (or temp directory), and the SIGQUIT handler
     // checks for the file.
-    private File createAttachFile(int pid, int ns_pid) throws IOException {
-        String fn = ".attach_pid" + ns_pid;
-        String path = "/proc/" + pid + "/cwd/" + fn;
-        File f = new File(path);
+    private File createAttachFile(long pid, long ns_pid) throws AttachNotSupportedException, IOException {
+        Path fn   = Path.of(".attach_pid" + ns_pid);
+        Path path = PROC.resolve(Path.of(Long.toString(pid), "cwd")).resolve(fn);
+        File f    = new File(path.toString());
         try {
             // Do not canonicalize the file path, or we will fail to attach to a VM in a container.
             f.createNewFile();
-        } catch (IOException x) {
-            String root = findTargetProcessTmpDirectory(pid, ns_pid);
-            f = new File(root, fn);
+        } catch (IOException e) {
+            f = new File(findTargetProcessTmpDirectory(pid, ns_pid), fn.toString());
             f.createNewFile();
         }
         return f;
     }
 
-    private String findTargetProcessTmpDirectory(int pid, int ns_pid) throws IOException {
-        String root;
-        if (pid != ns_pid) {
-            // A process may not exist in the same mount namespace as the caller, e.g.
-            // if we are trying to attach to a JVM process inside a container.
-            // Instead, attach relative to the target root filesystem as exposed by
-            // procfs regardless of namespaces.
-            String procRootDirectory = "/proc/" + pid + "/root";
-            if (!Files.isReadable(Path.of(procRootDirectory))) {
-                throw new IOException(
-                        String.format("Unable to access root directory %s " +
-                          "of target process %d", procRootDirectory, pid));
-            }
-
-            root = procRootDirectory + "/" + tmpdir;
-        } else {
-            root = tmpdir;
-        }
-        return root;
+    private String findTargetProcessTmpDirectory(long pid, long ns_pid) throws AttachNotSupportedException, IOException {
+        final var procPidRoot = PROC.resolve(Long.toString(pid)).resolve(ROOT_TMP);
+
+        /* We need to handle at least 4 different cases:
+         * 1. Caller and target processes share PID namespace and root filesystem (host to host or container to
+         *    container with both /tmp mounted between containers).
+         * 2. Caller and target processes share PID namespace and root filesystem but the target process has elevated
+         *    privileges (host to host).
+         * 3. Caller and target processes share PID namespace but NOT root filesystem (container to container).
+         * 4. Caller and target processes share neither PID namespace nor root filesystem (host to container)
+         *
+         * if target is elevated, we cant use /proc//... so we have to fallback to /tmp, but that may not be shared
+         * with the target/attachee process, we can try, except in the case where the ns_pid also exists in this pid ns
+         * which is ambiguous, if we share /tmp with the intended target, the attach will succeed, if we do not,
+         * then we will potentially attempt to attach to some arbitrary process with the same pid (in this pid ns)
+         * as that of the intended target (in its * pid ns).
+         *
+         * so in that case we should prehaps throw - or risk sending SIGQUIT to some arbitrary process... which could kill it
+         *
+         * however we can also check the target pid's signal masks to see if it catches SIGQUIT and only do so if in
+         * fact it does ... this reduces the risk of killing an innocent process in the current ns as opposed to
+         * attaching to the actual target JVM ... c.f: checkCatchesAndSendQuitTo() below.
+         *
+         * note that if pid == ns_pid we are in a shared pid ns with the target and may (potentially) share /tmp
+         */
+
+        return (Files.isWritable(procPidRoot) ? procPidRoot : TMPDIR).toString();
     }
 
     /*
@@ -269,13 +288,12 @@ private void writeString(int fd, String s) throws IOException {
         write(fd, b, 0, 1);
     }
 
-
     // Return the inner most namespaced PID if there is one,
     // otherwise return the original PID.
-    private int getNamespacePid(int pid) throws AttachNotSupportedException, IOException {
+    private long getNamespacePid(long pid) throws AttachNotSupportedException, IOException {
         // Assuming a real procfs sits beneath, reading this doesn't block
         // nor will it consume a lot of memory.
-        String statusFile = "/proc/" + pid + "/status";
+        final var statusFile = PROC.resolve(Long.toString(pid)).resolve(STATUS).toString();
         File f = new File(statusFile);
         if (!f.exists()) {
             return pid; // Likely a bad pid, but this is properly handled later.
@@ -291,8 +309,7 @@ private int getNamespacePid(int pid) throws AttachNotSupportedException, IOExcep
                     // The last entry represents the PID the JVM "thinks" it is.
                     // Even in non-namespaced pids these entries should be
                     // valid. You could refer to it as the inner most pid.
-                    int ns_pid = Integer.parseInt(parts[parts.length - 1]);
-                    return ns_pid;
+                    return Long.parseLong(parts[parts.length - 1]);
                 }
             }
             // Old kernels may not have NSpid field (i.e. 3.10).
@@ -303,6 +320,74 @@ private int getNamespacePid(int pid) throws AttachNotSupportedException, IOExcep
         }
     }
 
+    private static final String FIELD = "field";
+    private static final String MASK  = "mask";
+
+    private static final Pattern SIGNAL_MASK_PATTERN = Pattern.compile("(?<" + FIELD + ">Sig\\p{Alpha}{3}):\\s+(?<" + MASK + ">\\p{XDigit}{16}).*");
+
+    private static final long SIGQUIT = 0b100; // mask bit for SIGQUIT
+
+    private static boolean checkCatchesAndSendQuitTo(int pid, boolean throwIfNotReady) throws AttachNotSupportedException, IOException {
+        var quitIgn = false;
+        var quitBlk = false;
+        var quitCgt = false;
+
+        final var procPid = PROC.resolve(Integer.toString(pid));
+
+        var readBlk = false;
+        var readIgn = false;
+        var readCgt = false;
+
+
+        if (!Files.exists(procPid)) throw new IOException("non existent JVM pid: " + pid);
+
+        for (var line : Files.readAllLines(procPid.resolve("status"))) {
+
+            if (!line.startsWith("Sig")) continue; // to speed things up ... avoids the matcher/RE invocation...
+
+            final var m = SIGNAL_MASK_PATTERN.matcher(line);
+
+            if (!m.matches()) continue;
+
+            var       sigmask = m.group(MASK);
+            final var slen    = sigmask.length();
+
+            sigmask = sigmask.substring(slen / 2 , slen); // only really interested in the non r/t signals ...
+
+            final var sigquit = (Long.valueOf(sigmask, 16) & SIGQUIT) != 0L;
+
+            switch (m.group(FIELD)) {
+                case "SigBlk": { quitBlk = sigquit; readBlk = true; break; }
+                case "SigIgn": { quitIgn = sigquit; readIgn = true; break; }
+                case "SigCgt": { quitCgt = sigquit; readCgt = true; break; }
+            }
+
+            if (readBlk && readIgn && readCgt) break;
+        }
+
+        final boolean  okToSendQuit = (!quitIgn && quitCgt); // ignore blocked as it may be temporary ...
+
+        if (okToSendQuit) {
+            sendQuitTo(pid);
+        } else if (throwIfNotReady) {
+            Optional cmdline = Optional.empty();
+
+            try (final var clf = Files.lines(procPid.resolve("cmdline"))) {
+                cmdline = clf.findFirst();
+            }
+
+            var cmd = "null"; // default
+
+            if (cmdline.isPresent()) {
+                cmd = cmdline.get();
+                cmd = cmd.substring(0, cmd.length() - 1); // remove trailing \0
+            }
+
+            throw new AttachNotSupportedException("pid: " + pid + " cmd: '" + cmd + "' state is not ready to participate in attach handshake!");
+        }
+
+        return okToSendQuit;
+    }
 
     //-- native methods
 
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 000000000000..183a71ee8060
--- /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 0a62021633f9..aaafc373f80b 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
@@ -995,6 +995,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,
@@ -1423,6 +1425,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.jfr/share/classes/jdk/jfr/events/EventConfigurations.java b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
index bc4483646f1d..3ad5d6760be2 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
@@ -35,4 +35,10 @@ public final class EventConfigurations {
     public static final EventConfiguration FILE_FORCE = Utils.getConfiguration(FileForceEvent.class);
     public static final EventConfiguration ERROR_THROWN = Utils.getConfiguration(ErrorThrownEvent.class);
     public static final EventConfiguration EXCEPTION_THROWN = Utils.getConfiguration(ExceptionThrownEvent.class);
+
+    public static void initialize() {
+        // This method is intentionally empty. It is used to initialize the
+        // event configurations, i.e. ensure that this class's static
+        // initializer is run.
+    }
 }
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 a624a86f8b8a..c1d5cb5762bb 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
@@ -41,6 +41,7 @@ public final class PlatformEventType extends Type {
     private final boolean isJVM;
     private final boolean isJDK;
     private final boolean isMethodSampling;
+    private final boolean isBackToBackSensitive;
     private final List settings = new ArrayList<>(5);
     private final boolean dynamicSettings;
     private final int stackTraceOffset;
@@ -71,10 +72,25 @@ public final class PlatformEventType extends Type {
         this.dynamicSettings = dynamicSettings;
         this.isJVM = Type.isDefinedByJVM(id);
         this.isMethodSampling = isJVM && (name.equals(Type.EVENT_NAME_PREFIX + "ExecutionSample") || name.equals(Type.EVENT_NAME_PREFIX + "NativeMethodSample"));
+        this.isBackToBackSensitive = determineBackToBackSensitive();
         this.isJDK = isJDK;
         this.stackTraceOffset = stackTraceOffset(name, isJDK);
     }
 
+    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 static boolean isExceptionEvent(String name) {
         switch (name) {
             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 cf10a83ba649..5933b9045cb0 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
@@ -54,6 +54,7 @@
 import jdk.jfr.RecordingState;
 import jdk.jfr.events.ActiveRecordingEvent;
 import jdk.jfr.events.ActiveSettingEvent;
+import jdk.jfr.events.EventConfigurations;
 import jdk.jfr.internal.SecuritySupport.SafePath;
 import jdk.jfr.internal.SecuritySupport.SecureRecorderListener;
 import jdk.jfr.internal.consumer.EventLog;
@@ -83,6 +84,7 @@ public PlatformRecorder() throws Exception {
         Logger.log(JFR_SYSTEM, INFO, "Created native");
         JDKEvents.initialize();
         Logger.log(JFR_SYSTEM, INFO, "Registered JDK events");
+        EventConfigurations.initialize();
         JDKEvents.addInstrumentation();
         startDiskMonitor();
         shutdownHook = SecuritySupport.createThreadWitNoPermissions("JFR Shutdown Hook", new ShutdownHook(this));
@@ -281,7 +283,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));
@@ -353,7 +355,7 @@ synchronized void stop(PlatformRecording recording) {
                 finishChunk(currentChunk, stopTime, null);
             }
             currentChunk = newChunk;
-            PeriodicEvents.doChunkBegin();
+            PeriodicEvents.doChunkBegin(false);
         }
 
         if (toDisk) {
@@ -408,7 +410,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/periodic/PeriodicEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java
index 8695a5e0e391..5eadce37d51b 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
@@ -74,12 +74,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 228c5eb5c14e..ec738c6c1ce2 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/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp
index 551bba2b1344..ed2e0bb5b556 100644
--- a/test/hotspot/gtest/runtime/test_os.cpp
+++ b/test/hotspot/gtest/runtime/test_os.cpp
@@ -166,82 +166,95 @@ TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages,
 }
 #endif
 
-static void do_test_print_hex_dump(address addr, size_t len, int unitsize, const char* expected) {
-  char buf[256];
+#ifndef AIX
+// Test relies on the ability to protect memory allocated with os::reserve_memory. AIX may not be able
+// to do that (mprotect won't work on System V shm).
+static void do_test_print_hex_dump(const_address from, const_address to, int unitsize, int bytes_per_line,
+                                   const_address logical_start, const char* expected) {
+  char buf[2048];
   buf[0] = '\0';
   stringStream ss(buf, sizeof(buf));
-  os::print_hex_dump(&ss, addr, addr + len, unitsize);
-  // tty->print_cr("expected: %s", expected);
-  // tty->print_cr("result: %s", buf);
-  EXPECT_THAT(buf, HasSubstr(expected));
+  os::print_hex_dump(&ss, from, to, unitsize, /* print_ascii=*/true, bytes_per_line, logical_start);
+  EXPECT_STREQ(buf, expected);
 }
 
 TEST_VM(os, test_print_hex_dump) {
-  const char* pattern [4] = {
-#ifdef VM_LITTLE_ENDIAN
-    "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f",
-    "0100 0302 0504 0706 0908 0b0a 0d0c 0f0e",
-    "03020100 07060504 0b0a0908 0f0e0d0c",
-    "0706050403020100 0f0e0d0c0b0a0908"
+
+#ifdef _LP64
+#define ADDRESS1 "0x0000aaaaaaaaaa00"
+#define ADDRESS2 "0x0000aaaaaaaaaa20"
+#define ADDRESS3 "0x0000aaaaaaaaaa40"
 #else
-    "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f",
-    "0001 0203 0405 0607 0809 0a0b 0c0d 0e0f",
-    "00010203 04050607 08090a0b 0c0d0e0f",
-    "0001020304050607 08090a0b0c0d0e0f"
+#define ADDRESS1 "0xaaaaaa00"
+#define ADDRESS2 "0xaaaaaa20"
+#define ADDRESS3 "0xaaaaaa40"
 #endif
-  };
 
-  const char* pattern_not_readable [4] = {
-    "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??",
-    "???? ???? ???? ???? ???? ???? ???? ????",
-    "???????? ???????? ???????? ????????",
-    "???????????????? ????????????????"
-  };
+#define ASCII_1  "....#.jdk/internal/loader/Native"
+#define ASCII_2  "Libraries......."
+
+#define PAT_1 ADDRESS1 ":   ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??\n" \
+              ADDRESS2 ":   ff ff e0 dc 23 00 6a 64 6b 2f 69 6e 74 65 72 6e 61 6c 2f 6c 6f 61 64 65 72 2f 4e 61 74 69 76 65   " ASCII_1 "\n" \
+              ADDRESS3 ":   4c 69 62 72 61 72 69 65 73 00 00 00 00 00 00 00                                                   " ASCII_2 "\n"
 
-  // On AIX, zero page is readable.
-  address unreadable =
-#ifdef AIX
-    (address) 0xFFFFFFFFFFFF0000ULL;
+#ifdef VM_LITTLE_ENDIAN
+#define PAT_2 ADDRESS1 ":   ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ????\n" \
+              ADDRESS2 ":   ffff dce0 0023 646a 2f6b 6e69 6574 6e72 6c61 6c2f 616f 6564 2f72 614e 6974 6576   " ASCII_1 "\n" \
+              ADDRESS3 ":   694c 7262 7261 6569 0073 0000 0000 0000                                           " ASCII_2 "\n"
+
+#define PAT_4 ADDRESS1 ":   ???????? ???????? ???????? ???????? ???????? ???????? ???????? ????????\n" \
+              ADDRESS2 ":   dce0ffff 646a0023 6e692f6b 6e726574 6c2f6c61 6564616f 614e2f72 65766974   " ASCII_1 "\n" \
+              ADDRESS3 ":   7262694c 65697261 00000073 00000000                                       " ASCII_2 "\n"
+
+#define PAT_8 ADDRESS1 ":   ???????????????? ???????????????? ???????????????? ????????????????\n" \
+              ADDRESS2 ":   646a0023dce0ffff 6e7265746e692f6b 6564616f6c2f6c61 65766974614e2f72   " ASCII_1 "\n" \
+              ADDRESS3 ":   656972617262694c 0000000000000073                                     " ASCII_2 "\n"
 #else
-    (address) 0
-#endif
-    ;
+#define PAT_2 ADDRESS1 ":   ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ????\n" \
+              ADDRESS2 ":   ffff e0dc 2300 6a64 6b2f 696e 7465 726e 616c 2f6c 6f61 6465 722f 4e61 7469 7665   " ASCII_1 "\n" \
+              ADDRESS3 ":   4c69 6272 6172 6965 7300 0000 0000 0000                                           " ASCII_2 "\n"
 
-  ResourceMark rm;
-  char buf[64];
-  stringStream ss(buf, sizeof(buf));
-  outputStream* out = &ss;
-//  outputStream* out = tty; // enable for printout
-
-  // Test dumping unreadable memory
-  // Exclude test for Windows for now, since it needs SEH handling to work which cannot be
-  // guaranteed when we call directly into VM code. (see JDK-8220220)
-#ifndef _WIN32
-  do_test_print_hex_dump(unreadable, 100, 1, pattern_not_readable[0]);
-  do_test_print_hex_dump(unreadable, 100, 2, pattern_not_readable[1]);
-  do_test_print_hex_dump(unreadable, 100, 4, pattern_not_readable[2]);
-  do_test_print_hex_dump(unreadable, 100, 8, pattern_not_readable[3]);
+#define PAT_4 ADDRESS1 ":   ???????? ???????? ???????? ???????? ???????? ???????? ???????? ????????\n" \
+              ADDRESS2 ":   ffffe0dc 23006a64 6b2f696e 7465726e 616c2f6c 6f616465 722f4e61 74697665   " ASCII_1 "\n" \
+              ADDRESS3 ":   4c696272 61726965 73000000 00000000                                       " ASCII_2 "\n"
+
+#define PAT_8 ADDRESS1 ":   ???????????????? ???????????????? ???????????????? ????????????????\n" \
+              ADDRESS2 ":   ffffe0dc23006a64 6b2f696e7465726e 616c2f6c6f616465 722f4e6174697665   " ASCII_1 "\n" \
+              ADDRESS3 ":   4c69627261726965 7300000000000000                                     " ASCII_2 "\n"
 #endif
 
-  // Test dumping readable memory
-  address arr = (address)os::malloc(100, mtInternal);
-  for (int c = 0; c < 100; c++) {
-    arr[c] = c;
-  }
+  constexpr uint8_t bytes[] = {
+    0xff, 0xff, 0xe0, 0xdc, 0x23, 0x00, 0x6a, 0x64, 0x6b, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+    0x61, 0x6c, 0x2f, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65,
+    0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  };
+
+  // two pages, first one protected.
+  const size_t ps = os::vm_page_size();
+  char* two_pages = os::reserve_memory(ps * 2, false, mtTest);
+  os::commit_memory(two_pages, ps * 2, false);
+  os::protect_memory(two_pages, ps, os::MEM_PROT_NONE, true);
 
-  // properly aligned
-  do_test_print_hex_dump(arr, 100, 1, pattern[0]);
-  do_test_print_hex_dump(arr, 100, 2, pattern[1]);
-  do_test_print_hex_dump(arr, 100, 4, pattern[2]);
-  do_test_print_hex_dump(arr, 100, 8, pattern[3]);
+  memcpy(two_pages + ps, bytes, sizeof(bytes));
 
-  // Not properly aligned. Should automatically down-align by unitsize
-  do_test_print_hex_dump(arr + 1, 100, 2, pattern[1]);
-  do_test_print_hex_dump(arr + 1, 100, 4, pattern[2]);
-  do_test_print_hex_dump(arr + 1, 100, 8, pattern[3]);
+  // print
+  const const_address from = (const_address) two_pages + ps - 32;
+  const const_address to = (const_address) from + 32 + sizeof(bytes);
+  const const_address logical_start = (const_address) LP64_ONLY(0xAAAAAAAAAA00ULL) NOT_LP64(0xAAAAAA00ULL);
 
-  os::free(arr);
+  do_test_print_hex_dump(from, to, 1, 32, logical_start, PAT_1);
+  do_test_print_hex_dump(from, to, 2, 32, logical_start, PAT_2);
+  do_test_print_hex_dump(from, to, 4, 32, logical_start, PAT_4);
+  do_test_print_hex_dump(from, to, 8, 32, logical_start, PAT_8);
+
+  // unaligned printing, should align to next lower unitsize
+  do_test_print_hex_dump(from + 1, to, 2, 32, logical_start, PAT_2);
+  do_test_print_hex_dump(from + 1, to, 4, 32, logical_start, PAT_4);
+  do_test_print_hex_dump(from + 1, to, 8, 32, logical_start, PAT_8);
+
+  os::release_memory(two_pages, ps * 2);
 }
+#endif // not AIX
 
 //////////////////////////////////////////////////////////////////////////////
 // Test os::vsnprintf and friends.
@@ -939,3 +952,24 @@ TEST_VM(os, open_O_CLOEXEC) {
   ::close(fd);
 #endif
 }
+
+TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) {
+  char* p1 = os::reserve_memory(M, false, mtTest);
+  ASSERT_NE(p1, nullptr);
+  char* p2 = os::attempt_reserve_memory_at(p1, M);
+  ASSERT_EQ(p2, nullptr); // should have failed
+  os::release_memory(p1, M);
+}
+
+TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) {
+  if (UseLargePages && !os::can_commit_large_page_memory()) { // aka special
+    const size_t lpsz = os::large_page_size();
+    char* p1 = os::reserve_memory_aligned(lpsz, lpsz, false);
+    ASSERT_NE(p1, nullptr);
+    char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false);
+    ASSERT_EQ(p2, nullptr); // should have failed
+    os::release_memory(p1, M);
+  } else {
+    tty->print_cr("Skipped.");
+  }
+}
diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT
index 168c24034ba1..008528159f27 100644
--- a/test/hotspot/jtreg/TEST.ROOT
+++ b/test/hotspot/jtreg/TEST.ROOT
@@ -94,7 +94,7 @@ requires.properties= \
     jdk.containerized
 
 # Minimum jtreg version
-requiredVersion=7.3.1+1
+requiredVersion=7.4+1
 
 # Path to libraries in the topmost test directory. This is needed so @library
 # does not need ../../../ notation to reach them
diff --git a/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java
new file mode 100644
index 000000000000..2d5c20c2485b
--- /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
+ *                   compiler.loopopts.TestValidTypeInOverflowProtection
+ * @run main compiler.loopopts.TestValidTypeInOverflowProtection
+ */
+
+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;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java
index a9de46e00b0a..efe1fa4ffbcc 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 4b604096b00b..8c210544bb68 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/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java
index 643ad390dff7..3640f0ac587d 100644
--- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java
+++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java
@@ -39,14 +39,23 @@
  * @build EventGeneratorLoop
  * @run driver TestJcmdWithSideCar
  */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.nio.file.Paths;
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+
 import jdk.test.lib.Container;
+import jdk.test.lib.Platform;
 import jdk.test.lib.Utils;
 import jdk.test.lib.containers.docker.Common;
 import jdk.test.lib.containers.docker.DockerRunOptions;
@@ -61,6 +70,31 @@ public class TestJcmdWithSideCar {
     private static final long TIME_TO_WAIT_FOR_MAIN_METHOD_START = 50 * 1000; // milliseconds
     private static final String MAIN_CONTAINER_NAME = "test-container-main";
 
+    private static final String UID = "uid";
+    private static final String GID = "gid";
+
+    private static final Pattern ID_PATTERN = Pattern.compile("uid=(?<" + UID + ">\\d+)\\([^\\)]+\\)\\s+gid=(?<" + GID + ">\\d+).*");
+
+    private static final Optional USER = ProcessHandle.current().info().user().map(
+            user -> {
+                try (var br = new BufferedReader(new InputStreamReader(new ProcessBuilder("id", user).start().getInputStream()))) {
+                    for (final var line : br.lines().toList()) {
+                        final var m = ID_PATTERN.matcher(line);
+
+                        if (m.matches()) {
+                            return "--user=" + m.group(UID) + ":" + m.group(GID);
+                        }
+                    }
+                } catch (IOException e) {
+                    // do nothing...
+                }
+
+                return null;
+            }
+    );
+
+    private static final String NET_BIND_SERVICE = "--cap-add=NET_BIND_SERVICE";
+
     public static void main(String[] args) throws Exception {
         if (!DockerTestUtils.canTestDocker()) {
             return;
@@ -69,24 +103,33 @@ public static void main(String[] args) throws Exception {
         DockerTestUtils.buildJdkContainerImage(IMAGE_NAME);
 
         try {
-            // Start the loop process in the "main" container, then run test cases
-            // using a sidecar container.
-            MainContainer mainContainer = new MainContainer();
-            mainContainer.start();
-            mainContainer.waitForMainMethodStart(TIME_TO_WAIT_FOR_MAIN_METHOD_START);
-
-            long mainProcPid = testCase01();
-
-            // Excluding the test case below until JDK-8228850 is fixed
-            // JDK-8228850: jhsdb jinfo fails with ClassCastException:
-            // s.j.h.oops.TypeArray cannot be cast to s.j.h.oops.Instance
-            // mainContainer.assertIsAlive();
-            // testCase02(mainProcPid);
-
-            mainContainer.assertIsAlive();
-            testCase03(mainProcPid);
+            for (final boolean elevated : USER.isPresent() ? new Boolean[] { false, true } : new Boolean[] { false }) {
+                // Start the loop process in the "main" container, then run test cases
+                // using a sidecar container.
+                MainContainer mainContainer = new MainContainer();
+                mainContainer.start(elevated);
+                mainContainer.waitForMainMethodStart(TIME_TO_WAIT_FOR_MAIN_METHOD_START);
+
+                for (AttachStrategy attachStrategy : EnumSet.allOf(AttachStrategy.class)) {
+                    if (attachStrategy == AttachStrategy.ACCESS_TMP_VIA_PROC_ROOT &&
+                        elevated && !Platform.isRoot()) {
+                        // Elevated attach via proc/root not yet supported.
+                        continue;
+                    }
+                    long mainProcPid = testCase01(attachStrategy, elevated);
+
+                    // Excluding the test case below until JDK-8228850 is fixed
+                    // JDK-8228850: jhsdb jinfo fails with ClassCastException:
+                    // s.j.h.oops.TypeArray cannot be cast to s.j.h.oops.Instance
+                    // mainContainer.assertIsAlive();
+                    // testCase02(mainProcPid, attachStrategy, elevated);
+
+                    mainContainer.assertIsAlive();
+                    testCase03(mainProcPid, attachStrategy, elevated);
+                }
 
-            mainContainer.waitForAndCheck(TIME_TO_RUN_MAIN_PROCESS * 1000);
+                mainContainer.waitForAndCheck(TIME_TO_RUN_MAIN_PROCESS * 1000);
+            }
         } finally {
             DockerTestUtils.removeDockerImage(IMAGE_NAME);
         }
@@ -94,21 +137,21 @@ public static void main(String[] args) throws Exception {
 
 
     // Run "jcmd -l" in a sidecar container, find a target process.
-    private static long testCase01() throws Exception {
-        OutputAnalyzer out = runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "-l")
+    private static long testCase01(AttachStrategy attachStrategy, boolean elevated) throws Exception {
+        OutputAnalyzer out = runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "-l")
             .shouldHaveExitValue(0)
             .shouldContain("sun.tools.jcmd.JCmd");
         long pid = findProcess(out, "EventGeneratorLoop");
         if (pid == -1) {
-            throw new RuntimeException("Could not find specified process");
+            throw new RuntimeException(attachStrategy + ": Could not find specified process");
         }
 
         return pid;
     }
 
     // run jhsdb jinfo  (jhsdb uses PTRACE)
-    private static void testCase02(long pid) throws Exception {
-        runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jhsdb", "jinfo", "--pid", "" + pid)
+    private static void testCase02(long pid, AttachStrategy attachStrategy, boolean elevated) throws Exception {
+        runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jhsdb", "jinfo", "--pid", "" + pid)
             .shouldHaveExitValue(0)
             .shouldContain("Java System Properties")
             .shouldContain("VM Flags");
@@ -116,11 +159,11 @@ private static void testCase02(long pid) throws Exception {
 
     // test jcmd with some commands (help, start JFR recording)
     // JCMD will use signal mechanism and Unix Socket
-    private static void testCase03(long pid) throws Exception {
-        runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "help")
+    private static void testCase03(long pid, AttachStrategy attachStrategy, boolean elevated) throws Exception {
+        runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "" + pid, "help")
             .shouldHaveExitValue(0)
             .shouldContain("VM.version");
-        runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "JFR.start")
+        runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "" + pid, "JFR.start")
             .shouldHaveExitValue(0)
             .shouldContain("Started recording");
     }
@@ -128,21 +171,36 @@ private static void testCase03(long pid) throws Exception {
 
     // JCMD relies on the attach mechanism (com.sun.tools.attach),
     // which in turn relies on JVMSTAT mechanism, which puts its mapped
-    // buffers in /tmp directory (hsperfdata_). Thus, in sidecar
-    // we mount /tmp via --volumes-from from the main container.
-    private static OutputAnalyzer runSideCar(String mainContainerName, String whatToRun,
-                                             String... args) throws Exception {
-        List cmd = new ArrayList<>();
-        String[] command = new String[] {
+    // buffers in /tmp directory (hsperfdata_). Thus, in the sidecar
+    // we have two options:
+    // 1. mount /tmp from the main container using --volumes-from.
+    // 2. access /tmp from the main container via /proc//root/tmp.
+    private static OutputAnalyzer runSideCar(String mainContainerName, AttachStrategy attachStrategy, boolean elevated,  String whatToRun, String... args) throws Exception {
+        System.out.println("Attach strategy " + attachStrategy);
+
+        List initialCommands = List.of(
             Container.ENGINE_COMMAND, "run",
             "--tty=true", "--rm",
             "--cap-add=SYS_PTRACE", "--sig-proxy=true",
-            "--pid=container:" + mainContainerName,
-            "--volumes-from", mainContainerName,
-            IMAGE_NAME, whatToRun
+            "--pid=container:" + mainContainerName
+        );
+
+        List attachStrategyCommands = switch (attachStrategy) {
+            case TMP_MOUNTED_INTO_SIDECAR -> List.of("--volumes-from", mainContainerName);
+            case ACCESS_TMP_VIA_PROC_ROOT -> List.of();
         };
 
-        cmd.addAll(Arrays.asList(command));
+        List elevatedOpts = elevated && USER.isPresent() ? List.of(NET_BIND_SERVICE, USER.get()) : Collections.emptyList();
+
+        List imageAndCommand = List.of(
+            IMAGE_NAME, whatToRun
+        );
+
+        List cmd = new ArrayList<>();
+        cmd.addAll(initialCommands);
+        cmd.addAll(elevatedOpts);
+        cmd.addAll(attachStrategyCommands);
+        cmd.addAll(imageAndCommand);
         cmd.addAll(Arrays.asList(args));
         return DockerTestUtils.execute(cmd);
     }
@@ -189,9 +247,15 @@ static class MainContainer {
             }
         };
 
-        public Process start() throws Exception {
+        public Process start(final boolean elevated) throws Exception {
             // start "main" container (the observee)
             DockerRunOptions opts = commonDockerOpts("EventGeneratorLoop");
+
+            if (elevated && USER.isPresent()) {
+                opts.addDockerOpts(USER.get());
+                opts.addDockerOpts(NET_BIND_SERVICE);
+            }
+
             opts.addDockerOpts("--cap-add=SYS_PTRACE")
                 .addDockerOpts("--name", MAIN_CONTAINER_NAME)
                 .addDockerOpts("--volume", "/tmp")
@@ -242,7 +306,7 @@ public void waitForAndCheck(long timeout) throws Exception {
                 try {
                     exitValue = p.exitValue();
                 } catch(IllegalThreadStateException ex) {
-                    System.out.println("IllegalThreadStateException occured when calling exitValue()");
+                    System.out.println("IllegalThreadStateException occurred when calling exitValue()");
                     retryCount--;
                 }
             } while (exitValue == -1 && retryCount > 0);
@@ -254,4 +318,8 @@ public void waitForAndCheck(long timeout) throws Exception {
 
     }
 
+    private enum AttachStrategy {
+        TMP_MOUNTED_INTO_SIDECAR,
+        ACCESS_TMP_VIA_PROC_ROOT
+    }
 }
diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java
new file mode 100644
index 000000000000..208dd603615f
--- /dev/null
+++ b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java
@@ -0,0 +1,117 @@
+/*
+ * 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 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");
+        }
+        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 a75f314b53de..fe976291c8a0 100644
--- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
+++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
@@ -45,19 +45,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) {
@@ -71,7 +58,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/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java
index 2e9c97110b2a..62bd70dc61fb 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/containers/systemd/SystemdMemoryAwarenessTest.java b/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java
index 2c06d48bb1c0..ba77ce1c6e9d 100644
--- a/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java
+++ b/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Red Hat, Inc.
+ * Copyright (c) 2024, 2025, Red Hat, Inc.
  * 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,14 +68,14 @@ private static void testHelloSystemd() throws Exception {
 
         OutputAnalyzer out = SystemdTestUtils.buildAndRunSystemdJava(opts);
         out.shouldHaveExitValue(0)
-           .shouldContain("Hello Systemd")
-           .shouldContain(String.format("Memory Limit is: %d", (expectedMemLimit * MB)));
+           .shouldContain("Hello Systemd");
         try {
+            out.shouldContain(String.format("Memory Limit is: %d", (expectedMemLimit * MB)));
             out.shouldContain("OSContainer::active_processor_count: " + coreLimit);
         } catch (RuntimeException e) {
-            // CPU delegation needs to be enabled when run as user on cg v2
+            // CPU/memory delegation needs to be enabled when run as user on cg v2
             if (SystemdTestUtils.RUN_AS_USER) {
-                String hint = "When run as user on cg v2 cpu delegation needs to be configured!";
+                String hint = "When run as user on cg v2 cpu/memory delegation needs to be configured!";
                 throw new SkippedException(hint);
             }
             throw e;
diff --git a/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java
new file mode 100644
index 000000000000..5a705ffe8edb
--- /dev/null
+++ b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (C) 2025 THL A29 Limited, a Tencent company. 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.arguments;
+
+/*
+ * @test TestG1CompressedOops
+ * @bug 8354145
+ * @requires vm.flagless
+ * @summary Verify that the flag UseCompressedOops is updated properly
+ * @library /test/lib
+ * @library /
+ * @run driver gc.arguments.TestG1CompressedOops
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class TestG1CompressedOops {
+
+  private static void checkG1CompressedOops(String[] flags, boolean expectedValue, int exitValue) throws Exception {
+    ArrayList flagList = new ArrayList();
+    flagList.addAll(Arrays.asList(flags));
+    flagList.add("-XX:+UseG1GC");
+    flagList.add("-XX:+PrintFlagsFinal");
+    flagList.add("-version");
+
+    OutputAnalyzer output = GCArguments.executeTestJava(flagList);
+    output.shouldHaveExitValue(exitValue);
+
+    if (exitValue == 0) {
+      String stdout = output.getStdout();
+      boolean flagValue = getFlagValue("UseCompressedOops", stdout);
+      if (flagValue != expectedValue) {
+        throw new RuntimeException("Wrong value for UseCompressedOops. Expected " + expectedValue + " but got " + flagValue);
+      }
+    }
+  }
+
+  private static boolean getFlagValue(String flag, String where) {
+      Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\D+").matcher(where);
+      if (!m.find()) {
+          throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+      }
+      String match = m.group();
+      return match.contains("true");
+  }
+
+  public static void main(String args[]) throws Exception {
+    checkG1CompressedOops(new String[] { "-Xmx64m"   /* default is 1m */        }, true, 0);
+    checkG1CompressedOops(new String[] { "-Xmx64m",  "-XX:G1HeapRegionSize=2m"  }, true, 0);
+    checkG1CompressedOops(new String[] { "-Xmx32768m" /* 32g will turn off the usecompressedoops */  }, false, 0);
+    checkG1CompressedOops(new String[] { "-Xmx32760m" }, false, 0);
+    checkG1CompressedOops(new String[] { "-Xmx32736m", /* 32g - 32m will turn on the usecomppressedoops */ }, true, 0);
+
+    // if set G1HeapRegionSize explicitly with -Xmx32736m will turn off the UseCompressedOops
+    checkG1CompressedOops(new String[] { "-Xmx32736m", "-XX:G1HeapRegionSize=1m" }, false, 0);
+    checkG1CompressedOops(new String[] { "-Xmx32256m", "-XX:G1HeapRegionSize=512m" }, true, 0);
+  }
+}
diff --git a/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java b/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java
index a2c3f944db86..d14c9627314e 100644
--- a/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java
+++ b/test/hotspot/jtreg/runtime/Safepoint/TestAbortOnVMOperationTimeout.java
@@ -68,6 +68,7 @@ public static void testWith(int delay, boolean shouldPass) throws Exception {
                 "-XX:+AbortVMOnVMOperationTimeout",
                 "-XX:AbortVMOnVMOperationTimeoutDelay=" + delay,
                 "-Xmx256m",
+                "-XX:NewSize=64m",
                 "-XX:+UseSerialGC",
                 "-XX:-CreateCoredumpOnCrash",
                 "-Xlog:gc*=info",
diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
index cd559e591206..4b0bb7bd3343 100644
--- a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
+++ b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
@@ -8,6 +8,6 @@ classes-file=conf/classes.lst
 exclude-methods-file=conf/exclude.methods.lst
 print-complexity=true
 print-hierarchy=true
-disable-static=true
+disable-static=false
 generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory
 generators=JavaCode,ByteCode
diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java
index 0a77fbb7d2c3..0354559bf67d 100644
--- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java
+++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@ public StaticConstructorDefinition produce() throws ProductionFailedException {
                     .setOperatorLimit(operatorLimit)
                     .setLevel(level)
                     .setSubBlock(true)
-                    .setCanHaveBreaks(true)
+                    .setCanHaveBreaks(false)
                     .setCanHaveContinues(false)
                     .setCanHaveReturn(false)
                     .getBlockFactory()
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
index 6b33783306f2..15bbc9eb9642 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/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT
index a44ad3a7c015..8098695b80ec 100644
--- a/test/jaxp/TEST.ROOT
+++ b/test/jaxp/TEST.ROOT
@@ -23,7 +23,7 @@ modules=java.xml
 groups=TEST.groups
 
 # Minimum jtreg version
-requiredVersion=7.3.1+1
+requiredVersion=7.4+1
 
 # Path to libraries in the topmost test directory. This is needed so @library
 # does not need ../../ notation to reach them
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index c4ddcc93810d..7cdb152a190a 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -546,8 +546,6 @@ java/io/pathNames/GeneralWin32.java                             8180264 windows-
 
 # 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
@@ -562,7 +560,6 @@ sun/management/jdp/JdpOffTest.java                              8308807 aix-ppc6
 
 # jdk_jmx
 
-javax/management/MBeanServer/OldMBeanServerTest.java            8030957 aix-all
 
 javax/management/remote/mandatory/connection/RMIConnector_NPETest.java 8267887 generic-all
 
@@ -589,14 +586,10 @@ java/net/MulticastSocket/SetLoopbackMode.java                   7122846,8308807
 java/net/MulticastSocket/SetOutgoingIf.java                     8308807 aix-ppc64
 java/net/MulticastSocket/Test.java                              7145658,8308807 macosx-all,aix-ppc64
 
-java/net/Socket/asyncClose/Race.java                            8317801 aix-ppc64
-
 ############################################################################
 
 # jdk_nio
 
-java/nio/channels/Channels/SocketChannelStreams.java            8317838 aix-ppc64
-
 java/nio/channels/DatagramChannel/AdaptorMulticasting.java      8144003,8308807 macosx-all,aix-ppc64
 java/nio/channels/DatagramChannel/AfterDisconnect.java          8308807 aix-ppc64
 java/nio/channels/DatagramChannel/BasicMulticastTests.java      8144003 macosx-all
@@ -697,7 +690,6 @@ javax/swing/JFileChooser/bug6798062.java 8146446 windows-all
 javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all
 javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765  macosx-all,linux-all
 javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all
-javax/swing/JRadioButton/4314194/bug4314194.java 8298153 linux-all
 
 # Several tests which fail on some hidpi systems/macosx12-aarch64 system
 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64
diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT
index 778c6a78ddb1..fd0c95236698 100644
--- a/test/jdk/TEST.ROOT
+++ b/test/jdk/TEST.ROOT
@@ -115,7 +115,7 @@ requires.properties= \
     jdk.foreign.linker
 
 # Minimum jtreg version
-requiredVersion=7.3.1+1
+requiredVersion=7.4+1
 
 # Path to libraries in the topmost test directory. This is needed so @library
 # does not need ../../ notation to reach them
diff --git a/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java b/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java
index 98a0d9d98cef..7490d26fe6ff 100644
--- a/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java
+++ b/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,9 +113,11 @@ public class JdbStopInNotificationThreadTest extends JdbTest {
     private static final String DEBUGGEE_CLASS = JdbStopInNotificationThreadTestTarg.class.getName();
     private static final String PATTERN1_TEMPLATE = "^Breakpoint hit: \"thread=Notification Thread\", " +
             "JdbStopInNotificationThreadTestTarg\\$1\\.handleNotification\\(\\), line=%LINE_NUMBER.*\\R%LINE_NUMBER\\s+System\\.out\\.println\\(\"Memory usage low!!!\"\\);.*";
+    private static final String[] DEBUGGEE_OPTIONS = {"-Xmx256M"};
 
     private JdbStopInNotificationThreadTest() {
-        super(DEBUGGEE_CLASS);
+        super(new LaunchOptions(DEBUGGEE_CLASS)
+                .addDebuggeeOptions(DEBUGGEE_OPTIONS));
     }
 
     public static void main(String argv[]) {
diff --git a/test/jdk/com/sun/jdi/TwoThreadsTest.java b/test/jdk/com/sun/jdi/TwoThreadsTest.java
index e38783f3ea6e..e5732ffd8d13 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 66865f85942f..123c5120daf7 100644
--- a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java
+++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.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
@@ -30,10 +30,8 @@
  * @run testng/othervm LdapPoolTimeoutTest
  */
 
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import java.io.IOException;
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.naming.directory.InitialDirContext;
@@ -44,13 +42,8 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.TimeUnit;
 
 import static jdk.test.lib.Utils.adjustTimeout;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.expectThrows;
 
 public class LdapPoolTimeoutTest {
     /*
@@ -101,12 +94,13 @@ public void test() throws Exception {
             executorService.shutdown();
         }
         int failedCount = 0;
-        for (var f : futures) {
+        for (int i = 0; i < futures.size(); i++) {
             try {
-                f.get();
+                futures.get(i).get();
             } catch (ExecutionException e) {
                 failedCount++;
-                e.getCause().printStackTrace(System.out);
+                System.err.println("task " + (i + 1) + " failed:");
+                e.getCause().printStackTrace();
             }
         }
         if (failedCount > 0)
@@ -119,20 +113,31 @@ private static void attemptConnect(Hashtable env) throws Excepti
                    2 * CONNECT_MILLIS + TOLERANCE,
                    () -> new InitialDirContext(env));
         } catch (RuntimeException e) {
-            String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
-            System.err.println("MSG RTE: " + msg);
+            final String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
             // assertCompletion may wrap a CommunicationException in an RTE
-            assertNotNull(msg);
-            assertTrue(msg.contains("Network is unreachable")
-                        || msg.contains("No route to host") || msg.contains("Connection timed out"));
+            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;
+            }
         } catch (NamingException ex) {
-            String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage();
-            System.err.println("MSG: " + msg);
-            assertTrue(msg != null &&
+            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")));
+                        || msg.contains("Timeout exceeded while waiting for a connection"))) {
+                // got the expected exception
+                System.out.println("Received expected NamingException message: " + msg);
+            } else {
+                // propagate the unexpected exception
+                throw ex;
+            }
         } catch (Throwable t) {
             throw new RuntimeException(t);
         }
diff --git a/test/jdk/com/sun/tools/attach/java.policy.allow b/test/jdk/com/sun/tools/attach/java.policy.allow
index 3e63a207f61f..1d4b714c9029 100644
--- a/test/jdk/com/sun/tools/attach/java.policy.allow
+++ b/test/jdk/com/sun/tools/attach/java.policy.allow
@@ -1,6 +1,4 @@
 /*
- *
- *
  * Policy file used by unit tests for attach API
  */
 grant {
@@ -15,7 +13,10 @@ grant {
     permission java.lang.RuntimePermission "loadLibrary.attach";
     permission java.util.PropertyPermission "sun.jvmstat.*", "read";
 
-    /* to read configuration file in META-INF/services, and write/delete .attach_pid */
-    permission java.io.FilePermission "<>", "read,write,delete";
+    /* 
+     * To read configuration file in META-INF/services, write/delete .attach_pid, 
+     * and read symbolic link of /proc/self/ns/mnt.
+     */
+    permission java.io.FilePermission "<>", "read,write,delete,readlink";
 };
 
diff --git a/test/jdk/java/awt/Multiscreen/MultiScreenInsetsTest/MultiScreenInsetsTest.java b/test/jdk/java/awt/Multiscreen/MultiScreenInsetsTest/MultiScreenInsetsTest.java
deleted file mode 100644
index 610c21a1f6aa..000000000000
--- a/test/jdk/java/awt/Multiscreen/MultiScreenInsetsTest/MultiScreenInsetsTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2014, 2020, 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
-  @key headful
-  @bug 8020443
-  @summary Frame is not created on the specified GraphicsDevice with two
-monitors
-  @author Oleg Pekhovskiy
-  @library /test/lib
-  @build jdk.test.lib.Platform
-  @run main MultiScreenInsetsTest
- */
-
-import java.awt.Frame;
-import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
-import java.awt.Insets;
-import java.awt.Rectangle;
-import java.awt.Toolkit;
-
-import jdk.test.lib.Platform;
-
-public class MultiScreenInsetsTest {
-    private static final int SIZE = 100;
-
-    public static void main(String[] args) throws InterruptedException {
-        if (!Platform.isLinux()) {
-            System.out.println("This test is for Linux only..." +
-                               "skipping!");
-            return;
-        }
-
-        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        GraphicsDevice[] gds = ge.getScreenDevices();
-        if (gds.length < 2) {
-            System.out.println("It's a multi-screen test... skipping!");
-            return;
-        }
-
-        for (int screen = 0; screen < gds.length; ++screen) {
-            GraphicsDevice gd = gds[screen];
-            GraphicsConfiguration gc = gd.getDefaultConfiguration();
-            Rectangle bounds = gc.getBounds();
-            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
-
-            Frame frame = new Frame(gc);
-            frame.setLocation(bounds.x + (bounds.width - SIZE) / 2,
-                              bounds.y + (bounds.height - SIZE) / 2);
-            frame.setSize(SIZE, SIZE);
-            frame.setUndecorated(true);
-            frame.setVisible(true);
-
-            // Maximize Frame to reach the struts
-            frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
-            Thread.sleep(2000);
-
-            Rectangle frameBounds = frame.getBounds();
-            frame.dispose();
-            if (bounds.x + insets.left != frameBounds.x
-                || bounds.y + insets.top != frameBounds.y
-                || bounds.width - insets.right - insets.left != frameBounds.width
-                || bounds.height - insets.bottom - insets.top != frameBounds.height) {
-                throw new RuntimeException("Test FAILED! Wrong screen #" +
-                                           screen + " insets: " + insets);
-            }
-        }
-        System.out.println("Test PASSED!");
-    }
-}
diff --git a/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java b/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java
index 70ea3e379d7e..2cd05b08fc51 100644
--- a/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java
+++ b/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2022, 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
@@ -22,15 +22,14 @@
  */
 
 /*
-  @test
-  @key headful
-  @bug 4737732
-  @summary Tests that Toolkit.getScreenInsets() returns correct insets
-  @author artem.ananiev: area=awt.toplevel
-  @library ../../regtesthelpers
-  @build Util
-  @run main ScreenInsetsTest
-*/
+ * @test
+ * @key headful
+ * @bug 8020443 6899304 4737732
+ * @summary Tests that Toolkit.getScreenInsets() returns correct insets
+ * @library /test/lib
+ * @build jdk.test.lib.Platform
+ * @run main ScreenInsetsTest
+ */
 
 import java.awt.Frame;
 import java.awt.GraphicsConfiguration;
@@ -40,85 +39,77 @@
 import java.awt.Rectangle;
 import java.awt.Toolkit;
 
-import test.java.awt.regtesthelpers.Util;
+import jdk.test.lib.Platform;
 
-public class ScreenInsetsTest
-{
-    public static void main(String[] args)
-    {
-        boolean passed = true;
+public class ScreenInsetsTest {
+    private static final int SIZE = 100;
+    // Allow a margin tolerance of 1 pixel due to scaling
+    private static final int MARGIN_TOLERANCE = 1;
 
+    public static void main(String[] args) throws InterruptedException {
         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
         GraphicsDevice[] gds = ge.getScreenDevices();
-        for (GraphicsDevice gd : gds) {
+
+        for (int screen = 0; screen < gds.length; ++screen) {
+            GraphicsDevice gd = gds[screen];
             GraphicsConfiguration gc = gd.getDefaultConfiguration();
-            Rectangle gcBounds = gc.getBounds();
-            Insets gcInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
-            int left = gcInsets.left;
-            int right = gcInsets.right;
-            int bottom = gcInsets.bottom;
-            int top = gcInsets.top;
-            if (left < 0 || right < 0 || bottom < 0 || top < 0) {
-                throw new RuntimeException("Negative value: " + gcInsets);
-            }
-            int maxW = gcBounds.width / 3;
-            int maxH = gcBounds.height / 3;
-            if (left > maxW || right > maxW || bottom > maxH || top > maxH) {
-                throw new RuntimeException("Big value: " + gcInsets);
-            }
+            Rectangle bounds = gc.getBounds();
+            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
+            int workAreaWidth = bounds.width - insets.left - insets.right;
+            int workAreaHeight = bounds.height - insets.top - insets.bottom;
+            System.out.println("Screen #" + screen);
+            System.out.println("Screen Bounds: " + bounds);
+            System.out.println("Insets: " + insets);
+
+            Frame frame = new Frame(gc);
+            frame.setLocation(bounds.x + (bounds.width - SIZE) / 2,
+                    bounds.y + (bounds.height - SIZE) / 2);
+            frame.setSize(SIZE, SIZE);
 
-            if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH))
-            {
-                // this state is used in the test - sorry
-                continue;
+            /*
+             * On Windows, undecorated maximized frames are placed over the taskbar.
+             * Use a decorated frame instead.
+             */
+            if (Platform.isWindows()) {
+                frame.setUndecorated(false);
+            } else {
+                frame.setUndecorated(true);
             }
 
-            Frame f = new Frame("Test", gc);
-            f.setUndecorated(true);
-            f.setBounds(gcBounds.x + 100, gcBounds.y + 100, 320, 240);
-            f.setVisible(true);
-            Util.waitForIdle(null);
+            frame.setVisible(true);
 
-            f.setExtendedState(Frame.MAXIMIZED_BOTH);
-            Util.waitForIdle(null);
+            // Maximize Frame to reach the struts
+            frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
+            Thread.sleep(2000);
 
-            Rectangle fBounds = f.getBounds();
-            // workaround: on Windows maximized windows have negative coordinates
-            if (fBounds.x < gcBounds.x)
-            {
-                fBounds.width -= (gcBounds.x - fBounds.x) * 2; // width is decreased
-                fBounds.x = gcBounds.x;
+            Rectangle frameBounds = frame.getBounds();
+            System.out.println("Frame bounds: " + frameBounds);
+
+            frame.dispose();
+
+            /*
+             * On Windows, the top-left corner of an undecorated maximized frame
+             * may have negative coordinates (x, y).
+             * Adjust the frame bounds accordingly.
+             */
+            if (frameBounds.x < bounds.x) {
+                frameBounds.width -= (bounds.x - frameBounds.x) * 2;
+                frameBounds.x = bounds.x;
             }
-            if (fBounds.y < gcBounds.y)
-            {
-                fBounds.height -= (gcBounds.y - fBounds.y) * 2; // height is decreased
-                fBounds.y = gcBounds.y;
+            if (frameBounds.y < bounds.y) {
+                frameBounds.height -= (bounds.y - frameBounds.y) * 2;
+                frameBounds.y = bounds.y;
             }
-            Insets expected = new Insets(fBounds.y - gcBounds.y,
-                                         fBounds.x - gcBounds.x,
-                                         gcBounds.y + gcBounds.height - fBounds.y - fBounds.height,
-                                         gcBounds.x + gcBounds.width - fBounds.x - fBounds.width);
+            System.out.println("Adjusted Frame bounds: " + frameBounds);
 
-            // On Windows 10 and up system allows undecorated maximized windows
-            // to be placed over the taskbar so calculated insets might
-            // be smaller than reported ones depending on the taskbar position
-            if (gcInsets.top < expected.top
-                    || gcInsets.bottom < expected.bottom
-                    || gcInsets.left < expected.left
-                    || gcInsets.right < expected.right)
-            {
-                passed = false;
-                System.err.println("Wrong insets for GraphicsConfig: " + gc);
-                System.err.println("\tExpected: " + expected);
-                System.err.println("\tActual: " + gcInsets);
+            if (bounds.x + insets.left != frameBounds.x
+                    || bounds.y + insets.top != frameBounds.y
+                    || Math.abs(workAreaWidth - frameBounds.width) > MARGIN_TOLERANCE
+                    || Math.abs(workAreaHeight - frameBounds.height) > MARGIN_TOLERANCE) {
+                throw new RuntimeException("Test FAILED! Wrong screen #" +
+                        screen + " insets: " + insets);
             }
-
-            f.dispose();
-        }
-
-        if (!passed)
-        {
-            throw new RuntimeException("TEST FAILED: Toolkit.getScreenInsets() returns wrong value for some screens");
         }
+        System.out.println("Test PASSED!");
     }
 }
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 a12fd802fd5a..000000000000
--- 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
new file mode 100644
index 000000000000..9694043d1bb9
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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 8361748
+ * @summary Tests XBM image size limits and if XBMImageDecoder.produceImage()
+ *          throws appropriate error when parsing invalid XBM image data.
+ * @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 {
+
+    public static void main(String[] args) throws Exception {
+        String dir = System.getProperty("test.src");
+        PrintStream originalErr = System.err;
+        boolean validCase;
+
+        File currentDir = new File(dir);
+        File[] files = currentDir.listFiles((File d, String s)
+                                            -> s.endsWith(".xbm"));
+
+        for (File file : files) {
+            String fileName = file.getName();
+            validCase = fileName.startsWith("valid");
+
+            System.out.println("--- Testing " + fileName + " ---");
+            try (FileInputStream fis = new FileInputStream(file);
+                 ByteArrayOutputStream errContent = new ByteArrayOutputStream()) {
+                System.setErr(new PrintStream(errContent));
+
+                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 && 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.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm
new file mode 100644
index 000000000000..8a8cfc276322
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm
@@ -0,0 +1,2 @@
+#define k_ht 3
+h` k[] = { 01x0, 42222222222236319330::
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 000000000000..5cfb8e21cf87
--- /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
new file mode 100644
index 000000000000..1286eee1d9bb
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm
@@ -0,0 +1,3 @@
+#define k_width 16
+#define k_height  1
+k[] = { 0x10, 1234567890};
diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm
new file mode 100644
index 000000000000..5244651a4cb4
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm
@@ -0,0 +1,3 @@
+#define k_wt 16
+#define k_ht  0
+k[] = { 0x10, 0x12};
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 000000000000..714907084f29
--- /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.xbm b/test/jdk/java/awt/image/XBMDecoder/valid.xbm
new file mode 100644
index 000000000000..23b57b2c8116
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/valid.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[] = {
+0x13, 0x11, 0x15, 0x00, 0xAB, 0xcd };
diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm
new file mode 100644
index 000000000000..e365d8024472
--- /dev/null
+++ b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm
@@ -0,0 +1,4 @@
+#define test_width 16
+#define test_height 2
+static unsigned char test_bits[] = { 0x13, 0x11,
+ 0xAB, 0xff };
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 000000000000..e24bc10e9b0c
--- /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/lang/ProcessBuilder/SiblingIOEHandle.java b/test/jdk/java/lang/ProcessBuilder/SiblingIOEHandle.java
index 2e3cc0b78c8d..0aecae7dc405 100644
--- a/test/jdk/java/lang/ProcessBuilder/SiblingIOEHandle.java
+++ b/test/jdk/java/lang/ProcessBuilder/SiblingIOEHandle.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,6 +26,7 @@
  * @bug 6921885
  * @run main/othervm SiblingIOEHandle
  * @summary inherit IOE handles and MS CreateProcess limitations (kb315939)
+ * @requires (os.family == "windows")
  */
 
 import java.io.BufferedReader;
@@ -58,10 +59,6 @@ private static String[] getCommandArray(String processName) {
     }
 
     public static void main(String[] args) {
-        if (!System.getProperty("os.name").startsWith("Windows")) {
-            return;
-        }
-
         APP app = (args.length > 0) ? APP.valueOf(args[0]) : APP.A;
         switch (app) {
             case A:
diff --git a/test/jdk/java/lang/RuntimeTests/exec/Space.java b/test/jdk/java/lang/RuntimeTests/exec/Space.java
index 02debae34913..ef24376ce190 100644
--- a/test/jdk/java/lang/RuntimeTests/exec/Space.java
+++ b/test/jdk/java/lang/RuntimeTests/exec/Space.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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,13 +24,13 @@
 /* @test 1.4 00/10/18
    @bug 4231349
    @summary test runtime.exec on windows for extra space in cmd
+   @requires (os.family == "windows")
  */
 import java.io.*;
 
 public class Space {
     public static void main(String[] args) throws Exception {
-        if (File.separatorChar == '\\') {
-            try {
+        try {
             Process p = Runtime.getRuntime().exec( "cmd /c echo hello" );
             BufferedReader reader = new BufferedReader(
                                     new InputStreamReader(p.getInputStream()));
@@ -38,10 +38,9 @@ public static void main(String[] args) throws Exception {
             String echo = reader.readLine();
             if (echo.length() == 6)
                 throw new RuntimeException("Extra space in command.");
-            } catch (IOException e) {
-            // not Win NT - cmd doesnt exist
+        } catch (IOException e) {
+            // not Win NT - cmd doesn't exist
             return;
-            }
         }
     }
 }
diff --git a/test/jdk/java/lang/RuntimeTests/exec/Status.java b/test/jdk/java/lang/RuntimeTests/exec/Status.java
index 5a976c98f3da..ab0165c52e2c 100644
--- a/test/jdk/java/lang/RuntimeTests/exec/Status.java
+++ b/test/jdk/java/lang/RuntimeTests/exec/Status.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
  * @bug 4763362
  * @summary Ensure that Process.waitFor returns the correct status code
  *          even for very short-running subprocesses
+ * @requires (os.family == "linux")
  */
 
 
@@ -35,10 +36,6 @@ public class Status {
     public static void main(String args[])
         throws Exception
     {
-        if (!System.getProperty("os.name").equals("Linux")) {
-            System.out.println("Only for Linux");
-            return;
-        }
         UnixCommands.ensureCommandsAvailable("false");
 
         final String falseCmd = UnixCommands.findCommand("false");
diff --git a/test/jdk/java/lang/StringBuilder/RacingSBThreads.java b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java
new file mode 100644
index 000000000000..26f5cf9385a8
--- /dev/null
+++ b/test/jdk/java/lang/StringBuilder/RacingSBThreads.java
@@ -0,0 +1,303 @@
+/*
+ * 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 Test multi-threaded use of StringBuilder
+ * @compile --release 8 RacingSBThreads.java
+ * @run main/othervm -esa RacingSBThreads read
+ * @run main/othervm -esa RacingSBThreads insert
+ * @run main/othervm -esa RacingSBThreads append
+ * @run main/othervm -Xcomp RacingSBThreads
+ */
+
+import java.nio.CharBuffer;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+
+/**
+ * Test racing accesses in StringBuilder.
+ * Test source code should be compatible with JDK 8 to allow testing on older versions.
+ */
+public class RacingSBThreads {
+
+    private static final int TIMEOUT_SEC = 1;   // Duration to run each test case
+    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
+    private static final String UTF16_CHARS = initString('\u1000', LEN);
+    private static final String LATIN1_CHARS = initString('a', LEN);
+
+    // Cache jtreg timeout factor to allow test to be run as a standalone main()
+    private static final double TIMEOUT_FACTOR = Double.parseDouble(System.getProperty("test.timeout.factor", "1.0"));
+
+    // Constant arguments available to be passed to StringBuilder operations
+    private static final StringBuilder otherSB = new StringBuilder("ab\uFF21\uFF22");
+    private static final StringBuilder otherLongerSB = new StringBuilder("abcde\uFF21\uFF22\uFF23\uFF24\uFF25");
+
+    // Create a String with a repeated character
+    private static String initString(char c, int len) {
+        char[] chars = new char[len];
+        Arrays.fill(chars, c);
+        return new String(chars);
+    }
+
+    // Plain unsynchronized reference to a StringBuilder
+    // Updated by the writer thread
+    // Read by the reader thread
+    private StringBuilder buf;
+
+    // The current stress test case
+    private final StressKind stressKind;
+
+    // Count of faults, zero if no faults found
+    private final AtomicInteger faultCount = new AtomicInteger(0);
+
+    /**
+     * Run the stress cases indicated by command line arguments or run all cases.
+     * Running each for TIMEOUT_SEC seconds or until a failure.
+     * The timeout/test duration can be scaled by setting System property
+     * `test.timeout.factor` to a double value, for example, `-Dtest.timeout.factor=2.0`
+     * @param args command line arguments
+     */
+    public static void main(String[] args) {
+        Duration duration = Duration.ofSeconds((long)(TIMEOUT_SEC * TIMEOUT_FACTOR));
+
+        StressKind[] kinds = StressKind.values();
+        if (args.length > 0) {
+            // Parse explicitly supplied StressKind arguments
+            try {
+                 kinds = Arrays.stream(args)
+                         .map((s) -> StressKind.valueOf(s.toUpperCase(Locale.ROOT)))
+                         .toArray(StressKind[]::new);
+            } catch (Exception ex) {
+                System.out.println("Invalid StressKind arguments: " + Arrays.toString(args));
+                return;
+            }
+        }
+
+        // Run each kind for the duration
+        int totalFaults = 0;
+        for (StressKind sk : kinds) {
+            Instant end = Instant.now().plus(duration); // note clock time, not runtime
+            while (Instant.now().isBefore(end)) {
+                int faultCount = new RacingSBThreads(sk).stress();
+                if (faultCount > 0) {
+                    System.out.printf("ERROR: Test case %s, %d faults%n", sk, faultCount);
+                }
+                totalFaults += faultCount;
+            }
+        }
+        if (totalFaults > 0) {
+            throw new AssertionError("Total faults: " + totalFaults);
+        }
+    }
+
+    // Enum of the various test cases with a lambda to invoke for each
+    enum StressKind {
+        /**
+         * Reading characters should always be one of the known values being written to the destination
+         */
+        READ(LATIN1_CHARS, (sb,  chr) -> {
+            char ch = sb.charAt(LEN * 4 / 5);
+            if (ch != chr & ch != (chr & 0xff) & ch != chr >> 8) {
+                throw new AssertionError("Unexpected characters in buffer: 0x" + Integer.toHexString(ch));
+            }
+        }),
+        /**
+         * Insert another StringBuilder; in the face of racy changes to the destination
+         */
+        INSERT(LATIN1_CHARS, (sb, C) -> {
+            sb.insert(sb.length() - 1, otherLongerSB, 0, otherLongerSB.length());
+        }),
+        /**
+         * Appending a StringBuilder in the face of racy changes to the destination
+         */
+        APPEND(LATIN1_CHARS, (sb, C) -> {
+            sb.append(otherSB, 0, otherSB.length());
+        }),
+        ;
+
+        private final BiConsumer func;
+        private final String sbInitString;
+
+        /**
+         * Defines a test case.
+         * @param sbInitString the initial contents of the StringBuilder; chooses the coder
+         * @param func the test BiConsumer to apply to the StringBuilder
+         */
+        private StressKind(String sbInitString, BiConsumer func) {
+            this.func = func;
+            this.sbInitString = sbInitString;
+        }
+    }
+
+    public RacingSBThreads(StressKind stressKind) {
+        this.stressKind = stressKind;
+    }
+
+    /**
+     * Run the stress case.
+     * One thread continuously creates a StringBuilder and fills it before trimming it to zero.
+     * The other thread performs the test case on the same StringBuilder (without any synchronization)
+     * @return the count of faults
+     */
+    private int stress() {
+        PokeBuilder r = new PokeBuilder(this, N);
+        Writer w = new Writer(this, N);
+
+        Thread writer = new Thread(w::createShrink);
+        Thread reader = new Thread(r::readModify);
+        writer.start();
+        reader.start();
+        join(reader);
+        System.out.println(r);
+        writer.interrupt();
+        join(writer);
+        System.out.println(w);
+        return r.racing.faultCount.get();
+    }
+
+    /**
+     * Wait for a thread to terminate.
+     * @param thread a thread to wait for
+     */
+    private void join(Thread thread) {
+        do {
+            try {
+                thread.join();
+                break;
+            } catch (InterruptedException ie) {
+                // ignore and retry
+            }
+        } while (true);
+    }
+
+    /**
+     * Run a StressKind case in a loop keeping track of exceptions.
+     * The StringBuilder under test is shared with the writer task without benefit of synchronization.
+     */
+    private static class PokeBuilder {
+        private final RacingSBThreads racing;
+        private final int iterations;
+        private int nulls;
+        private int bounds;
+        private int pokeCycles;
+        private int bufChanges;
+
+        public PokeBuilder(RacingSBThreads racing, int iterations) {
+            this.racing = racing;
+            this.iterations = iterations;
+            nulls = 0;
+            bounds = 0;
+            pokeCycles = 0;
+            bufChanges = 0;
+        }
+
+        // Repeatedly change the racy StringBuilder, ignoring and counting exceptions
+        private void readModify() {
+            System.out.println("Starting " + racing.stressKind);
+            sleep(100);
+            for (int i = 0; i < iterations; ++i) {
+                pokeCycles++;
+                StringBuilder sb = racing.buf;  // read once
+                try {
+                    if (sb.length() > Integer.MAX_VALUE / 4) {
+                        sb.setLength(Integer.MAX_VALUE / 4);
+                    }
+                    // Invoke the test case
+                    racing.stressKind.func.accept(sb, racing.stressKind.sbInitString.charAt(0));
+                    if (sb != racing.buf) {
+                        bufChanges++;
+                    }
+                } catch (NullPointerException e) {
+                    ++nulls;
+                } catch (IndexOutOfBoundsException e) {
+                    ++bounds;
+                } catch (AssertionError ae) {
+                    racing.faultCount.incrementAndGet();
+                    throw ae;
+                }
+            }
+        }
+
+        private static void sleep(int i) {
+            try {
+                Thread.sleep(i);
+            } catch (InterruptedException ignored) {
+            }
+        }
+
+        public String toString() {
+            return String.format("pokeCycles:%d, bounds:%d, bufChanges:%d, nulls=%d",
+                    pokeCycles, bounds, bufChanges, nulls);
+        }
+    }
+
+    /**
+     * Repeatedly create and append strings to a StringBuilder shared through fields of RacingSBThreads.
+     * The StringBuilder is created new on each iteration and truncated at the end of each iteration.
+     * Exceptions are counted and reported.
+     */
+    private static class Writer {
+        private final RacingSBThreads racing;
+        private final int iterations;
+        private int sumWriter;
+        private int writeCycles;
+        private int putBounds;
+
+        public Writer(RacingSBThreads racing, int iterations) {
+            this.racing = racing;
+            this.iterations = iterations;
+        }
+
+        private void createShrink() {
+            for (int i = 0; i < iterations; ++i) {
+                if (i % 100_000 == 0) {
+                    if (Thread.interrupted()) {
+                        break;
+                    }
+                }
+                try {
+                    ++writeCycles;
+                    racing.buf = new StringBuilder(racing.stressKind.sbInitString);
+                    racing.buf.append(UTF16_CHARS);
+                    sumWriter += racing.buf.length();
+                    racing.buf.setLength(0);
+                    racing.buf.trimToSize();
+                } catch (Exception ex) {
+                    ++putBounds;
+                }
+            }
+        }
+
+        public String toString() {
+            return String.format("writeCycles:%d, bounds:%d, sumWriter=%d", writeCycles, putBounds, sumWriter);
+        }
+    }
+}
diff --git a/test/jdk/java/lang/System/NonAnsiFileEncodingTest.java b/test/jdk/java/lang/System/NonAnsiFileEncodingTest.java
deleted file mode 100644
index 1683e7117650..000000000000
--- a/test/jdk/java/lang/System/NonAnsiFileEncodingTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2018, 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 4459099
- * @key i18n
- * @summary Tests non ANSI code page locales set default file encoding
- * to "utf-8".  This test must be run on Windows 2K/XP in one of Armenian,
- * Georgian, Hindi, Punjabi, Gujarati, Tamil, Telugu, Kannada, Marathi,
- * or Sanskrit languages.
- */
-
-public class NonAnsiFileEncodingTest {
-    public static void main(String[] s)  {
-        String OS = System.getProperty("os.name");
-        String lang = System.getProperty("user.language");
-        String fileenc = System.getProperty("file.encoding");
-
-        if (!(OS.equals("Windows 2000") || OS.equals("Windows XP"))) {
-            System.out.println("This test is not meaningful on the platform \"" + OS + "\".");
-            return;
-        }
-
-        if (!(lang.equals("hy") ||      // Armenian
-              lang.equals("ka") ||      // Georgian
-              lang.equals("hi") ||      // Hindi
-              lang.equals("pa") ||      // Punjabi
-              lang.equals("gu") ||      // Gujarati
-              lang.equals("ta") ||      // Tamil
-              lang.equals("te") ||      // Telugu
-              lang.equals("kn") ||      // Kannada
-              lang.equals("mr") ||      // Marathi
-              lang.equals("sa"))) {     // Sanskrit
-            System.out.println("Windows' locale settings for this test is incorrect.  Select one of \"Armenian\", \"Georgian\", \"Hindi\", \"Punjabi\", \"Gujarati\", \"Tamil\", \"Telugu\", \"Kannada\", \"Marathi\", or \"Sanskrit\" for the user locale, and \"English(United States)\" for the system default locale using the Control Panel.");
-            return;
-        }
-
-        if (!fileenc.equals("utf-8")) {
-            throw new RuntimeException("file.encoding is incorrectly set to \"" + fileenc + "\".  Should be \"utf-8\".");
-        }
-    }
-}
diff --git a/test/jdk/java/nio/file/Files/CopyInterference.java b/test/jdk/java/nio/file/Files/CopyInterference.java
new file mode 100644
index 000000000000..310d3e382cad
--- /dev/null
+++ b/test/jdk/java/nio/file/Files/CopyInterference.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8114830
+ * @summary Verify FileAlreadyExistsException is not thrown for REPLACE_EXISTING
+ * @library ..
+ * @build CopyInterference
+ * @run junit CopyInterference
+ */
+import java.io.InputStream;
+import java.io.IOException;
+import java.nio.file.CopyOption;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.FileSystemException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import static java.nio.file.StandardCopyOption.*;
+import static java.nio.file.LinkOption.*;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class CopyInterference {
+
+    private static final int N_THREADS = 2;
+
+    private static final AtomicBoolean running = new AtomicBoolean(true);
+
+    private static class CopyTask implements Runnable {
+        final Path source;
+        final Path target;
+        final CopyOption[] options;
+
+        CopyTask(Path source, Path target, CopyOption[] options) {
+            this.source = source;
+            this.target = target;
+            this.options = options;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (running.get()) {
+                    Files.copy(source, target, options);
+                }
+            } catch (FileAlreadyExistsException e) {
+                throw new RuntimeException("Unexpected exception", e);
+            } catch (FileSystemException e) {
+                System.out.printf("Expected FileSystemException: \"%s\"%n",
+                                  e.getMessage());
+            } catch (IOException e) {
+                throw new RuntimeException("Unexpected exception", e);
+            } finally {
+                running.set(false);
+            }
+        }
+    }
+
+    private static Stream pathAndOptionsProvider()
+        throws IOException {
+        Path parent = Path.of(System.getProperty("test.dir", "."));
+        Path dir = Files.createTempDirectory(parent, "foobargus");
+
+        List list = new ArrayList();
+
+        // regular file
+        Path sourceFile = Files.createTempFile(dir, "foo", "baz");
+        Class c = CopyInterference.class;
+        String name = "CopyInterference.class";
+
+        try (InputStream in = c.getResourceAsStream(name)) {
+            Files.copy(in, sourceFile, REPLACE_EXISTING);
+        }
+
+        Arguments args = Arguments.of(sourceFile, dir.resolve("targetFile"),
+                                      new CopyOption[] {REPLACE_EXISTING});
+        list.add(args);
+
+        // directory
+        Path sourceDirectory = Files.createTempDirectory(dir, "fubar");
+        args = Arguments.of(sourceDirectory, dir.resolve("targetDir"),
+                            new CopyOption[] {REPLACE_EXISTING});
+        list.add(args);
+
+        if (TestUtil.supportsLinks(dir)) {
+            // symbolic link, followed
+            Path link = dir.resolve("link");
+            Files.createSymbolicLink(link, sourceFile);
+            args = Arguments.of(link, dir.resolve("linkFollowed"),
+                                new CopyOption[] {REPLACE_EXISTING});
+            list.add(args);
+
+            // symbolic link, not followed
+            args = Arguments.of(link, dir.resolve("linkNotFollowed"),
+                                new CopyOption[] {REPLACE_EXISTING,
+                                                  NOFOLLOW_LINKS});
+            list.add(args);
+        } else {
+            System.out.println("Links not supported: not testing links");
+        }
+
+        return list.stream();
+    }
+
+    @ParameterizedTest
+    @MethodSource("pathAndOptionsProvider")
+    void copy(Path source, Path target, CopyOption[] options)
+        throws InterruptedException, IOException {
+
+        Future[] results = new Future[N_THREADS];
+        try (ExecutorService es = Executors.newFixedThreadPool(N_THREADS)) {
+            CopyTask copyTask = new CopyTask(source, target, options);
+            for (int i = 0; i < N_THREADS; i++)
+                results[i] = es.submit(copyTask);
+        }
+
+        for (Future res : results) {
+            try {
+                res.get();
+            } catch (ExecutionException e) {
+                throw new RuntimeException(res.exceptionNow());
+            }
+        }
+    }
+}
diff --git a/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java b/test/jdk/java/rmi/server/RemoteServer/AddrInUse.java
index 34e343b61932..86ac5b0313b9 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/security/KeyStore/TestDisabledAlgorithms.java b/test/jdk/java/security/KeyStore/TestDisabledAlgorithms.java
new file mode 100644
index 000000000000..0c060a45b7ed
--- /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 000000000000..413898e0c706
--- /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/Signature/TestDisabledAlgorithms.java b/test/jdk/java/security/Signature/TestDisabledAlgorithms.java
new file mode 100644
index 000000000000..cdecf113d80b
--- /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/text/testlib/HexDumpReader.java b/test/jdk/java/text/testlib/HexDumpReader.java
index 61fcf27832a6..1fe3732dec17 100644
--- a/test/jdk/java/text/testlib/HexDumpReader.java
+++ b/test/jdk/java/text/testlib/HexDumpReader.java
@@ -21,15 +21,14 @@
  * questions.
  */
 
-import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.FileInputStream;
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
+import java.nio.file.Files;
+import java.util.HexFormat;
+import java.util.stream.Collectors;
 
 /**
  * HexDumpReader provides utility methods to read a hex dump text file
@@ -43,78 +42,33 @@ public final class HexDumpReader {
     // Utility class should not be instantiated
     private HexDumpReader() {}
 
-    public static InputStream getStreamFromHexDump(String fileName) {
+    /*
+     * Converts a Hex dump file given by the String name into an InputStream
+     * containing bytes. The expected format of the file should be given as lines
+     * that are either:
+     *  - Valid hexadecimal value(s) (two hexadecimal characters) combined with no
+     *    spaces between. E.g. "ace95365" represents four hexadecimal values.
+     *    There should not be an odd amount of hexadecimal characters. E.g. "ace"
+     *  - Contain leading comments given by '#' (which are ignored). E.g. "#foo"
+     *    Non-leading comments are not allowed. E.g. "ace953 #foo"
+     *  - Empty (which are ignored).
+     */
+    public static InputStream getStreamFromHexDump(String fileName) throws IOException {
         return getStreamFromHexDump(new File(System.getProperty("test.src", "."),
-                                             fileName));
+                fileName));
     }
 
-    public static InputStream getStreamFromHexDump(File hexFile) {
-        ByteArrayBuilder bab = new ByteArrayBuilder();
-        int lineNo = 0;
-        try (BufferedReader reader
-                 = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile),
-                StandardCharsets.US_ASCII))) {
-            String line;
-            while ((line = reader.readLine()) != null) {
-                lineNo++;
-                line = line.trim();
-                // Skip blank and comment lines.
-                if (line.length() == 0) {
-                    continue;
-                }
-                int x = line.indexOf('#');
-                if (x == 0) {
-                    continue;
-                }
-                if (x > 0) {
-                    line = line.substring(0, x).trim();
-                }
-                int len = line.length();
-                for (int i = 0; i < len; i += 2) {
-                    bab.put((byte)Integer.parseInt(line, i, i + 2, 16));
-                }
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e);
-        }
-        return new ByteArrayInputStream(bab.toArray());
+    // Overloaded version of getStreamFromHexDump() that takes the File itself as input.
+    public static InputStream getStreamFromHexDump(File hexFile) throws IOException {
+        // This hexString should only consist of valid hexadecimal digits and be even
+        // otherwise an exception will be thrown when converting to bytes
+        String hexString = Files.readAllLines(hexFile.toPath(), StandardCharsets.UTF_8)
+                .stream()
+                .map(String::trim)
+                .filter(s -> !s.isEmpty() && !s.startsWith("#"))
+                .collect(Collectors.joining());
+        // Iterate the hex string and convert it to bytes
+        byte[] bArray = HexFormat.of().parseHex(hexString);
+        return new ByteArrayInputStream(bArray);
     }
-
-
-    private static class ByteArrayBuilder {
-        private static final int BUFFER_SIZE = 4096;
-
-        private int size;
-        private List bytes;
-        private byte[] current;
-        private int offset;
-
-        ByteArrayBuilder() {
-            bytes = new ArrayList<>();
-            current = new byte[BUFFER_SIZE];
-        }
-
-        void put(byte b) {
-            if (offset == BUFFER_SIZE) {
-                bytes.add(current);
-                current = new byte[BUFFER_SIZE];
-                offset = 0;
-            }
-            current[offset++] = b;
-            size++;
-        }
-
-        byte[] toArray() {
-            byte[] buf = new byte[size];
-            int ptr = 0;
-            for (byte[] ba : bytes) {
-                System.arraycopy(ba, 0, buf, ptr, ba.length);
-                ptr += ba.length;
-            }
-            System.arraycopy(current, 0, buf, ptr, offset);
-            assert ptr + offset == size;
-            return buf;
-        }
-    }
-
 }
diff --git a/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java b/test/jdk/javax/crypto/Cipher/TestDisabledAlgorithms.java
new file mode 100644
index 000000000000..3505552d1b14
--- /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 000000000000..d1d9fa7a5bbd
--- /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 000000000000..56e35f2a72ae
--- /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/SSLSession/CertMsgCheck.java b/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java
index 498c17672b21..2131b314ce0a 100644
--- a/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java
+++ b/test/jdk/javax/net/ssl/SSLSession/CertMsgCheck.java
@@ -39,10 +39,12 @@ public static void main(String[] args) throws Exception {
             build();
 
         // Initial client session
-        TLSBase.Client client1 = new TLSBase.Client(true, false);
+        TLSBase.Client client = new TLSBase.Client(true, false);
+        client.connect();
 
-        server.getSession(client1).getSessionContext();
-        server.done();
+        // Close must be called to gather all the exceptions thrown
+        client.close();
+        server.close();
 
         var eList = server.getExceptionList();
         System.out.println("Exception list size is " + eList.size());
diff --git a/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java b/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java
index 183354ed9db2..a08414b03fd4 100644
--- a/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java
+++ b/test/jdk/javax/net/ssl/SSLSession/CheckSessionContext.java
@@ -47,6 +47,7 @@ public static void main(String[] args) throws Exception {
 
         // Initial client session
         TLSBase.Client client1 = new TLSBase.Client();
+        client1.connect();
         if (server.getSession(client1).getSessionContext() == null) {
             throw new Exception("Context was null.  Handshake failure.");
         } else {
@@ -66,6 +67,7 @@ public static void main(String[] args) throws Exception {
 
         // Resume the client session
         TLSBase.Client client2 = new TLSBase.Client();
+        client2.connect();
         if (server.getSession(client2).getSessionContext() == null) {
             throw new Exception("Context was null on resumption");
         } else {
@@ -73,6 +75,5 @@ public static void main(String[] args) throws Exception {
         }
         server.close(client2);
         client2.close();
-        server.done();
     }
 }
diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/AbstractPeer.java
index 1bfc3ebcdbb2..9950caf19215 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 91d1a8d1ead6..7d3cb7d16657 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 b07a039203e2..a6c8a13e0c66 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/TLSBase.java b/test/jdk/javax/net/ssl/templates/TLSBase.java
index 5c95253e6f02..73951ce94222 100644
--- a/test/jdk/javax/net/ssl/templates/TLSBase.java
+++ b/test/jdk/javax/net/ssl/templates/TLSBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,13 @@
 import java.io.*;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
 import java.security.KeyStore;
 import java.security.cert.PKIXBuilderParameters;
 import java.security.cert.X509CertSelector;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.*;
 
 /**
  * This is a base setup for creating a server and clients.  All clients will
@@ -39,7 +39,7 @@
  * first.  The idea is for the test code to be minimal as possible without
  * this library class being complicated.
  *
- * Server.done() must be called or the server will never exit and hang the test.
+ * Server.close() must be called so the server will exit and end threading.
  *
  * After construction, reading and writing are allowed from either side,
  * or a combination write/read from both sides for verifying text.
@@ -52,24 +52,25 @@
  */
 
 abstract public class TLSBase {
-    static String pathToStores = "../etc";
+    static String pathToStores = "javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
 
+    static final String TESTROOT =
+        System.getProperty("test.root", "../../../..");
+
     SSLContext sslContext;
     // Server's port
     static int serverPort;
     // Name shown during read and write ops
-    String name;
+    public String name;
 
     TLSBase() {
-        String keyFilename =
-            System.getProperty("test.src", "./") + "/" + pathToStores +
-                "/" + keyStoreFile;
-        String trustFilename =
-            System.getProperty("test.src", "./") + "/" + pathToStores +
-                "/" + trustStoreFile;
+
+        String keyFilename = TESTROOT +  "/" + pathToStores + "/" + keyStoreFile;
+        String trustFilename = TESTROOT + "/" + pathToStores + "/" +
+            trustStoreFile;
         System.setProperty("javax.net.ssl.keyStore", keyFilename);
         System.setProperty("javax.net.ssl.keyStorePassword", passwd);
         System.setProperty("javax.net.ssl.trustStore", trustFilename);
@@ -78,26 +79,24 @@ abstract public class TLSBase {
 
     // Base read operation
     byte[] read(SSLSocket sock) throws Exception {
-        BufferedReader reader = new BufferedReader(
-            new InputStreamReader(sock.getInputStream()));
-        String s = reader.readLine();
-        System.err.println("(read) " + name + ": " + s);
-        return s.getBytes();
+        BufferedInputStream is = new BufferedInputStream(sock.getInputStream());
+        byte[] b = is.readNBytes(5);
+        System.err.println("(read) " + Thread.currentThread().getName() + ": " +
+            new String(b));
+        return b;
     }
 
     // Base write operation
     public void write(SSLSocket sock, byte[] data) throws Exception {
-        PrintWriter out = new PrintWriter(
-            new OutputStreamWriter(sock.getOutputStream()));
-        out.println(new String(data));
-        out.flush();
-        System.err.println("(write)" + name + ": " + new String(data));
+        sock.getOutputStream().write(data);
+        System.err.println("(write)" + Thread.currentThread().getName() + ": " +
+            new String(data));
     }
 
     private static KeyManager[] getKeyManager(boolean empty) throws Exception {
         FileInputStream fis = null;
         if (!empty) {
-            fis = new FileInputStream(System.getProperty("test.src", "./") +
+            fis = new FileInputStream(System.getProperty("test.root", "./") +
                 "/" + pathToStores + "/" + keyStoreFile);
         }
         // Load the keystore
@@ -113,7 +112,7 @@ private static KeyManager[] getKeyManager(boolean empty) throws Exception {
     private static TrustManager[] getTrustManager(boolean empty) throws Exception {
         FileInputStream fis = null;
         if (!empty) {
-            fis = new FileInputStream(System.getProperty("test.src", "./") +
+            fis = new FileInputStream(System.getProperty("test.root", "./") +
                 "/" + pathToStores + "/" + trustStoreFile);
         }
         // Load the keystore
@@ -148,9 +147,9 @@ static class Server extends TLSBase {
         // Clients sockets are kept in a hash table with the port as the key.
         ConcurrentHashMap clientMap =
                 new ConcurrentHashMap<>();
-        Thread t;
         List exceptionList = new ArrayList<>();
-
+        ExecutorService threadPool = Executors.newFixedThreadPool(1);
+        CountDownLatch serverLatch = new CountDownLatch(1);
         Server(ServerBuilder builder) {
             super();
             name = "server";
@@ -160,128 +159,82 @@ static class Server extends TLSBase {
                     TLSBase.getTrustManager(builder.tm), null);
                 fac = sslContext.getServerSocketFactory();
                 ssock = (SSLServerSocket) fac.createServerSocket(0);
+                ssock.setReuseAddress(true);
                 ssock.setNeedClientAuth(builder.clientauth);
                 serverPort = ssock.getLocalPort();
+                System.err.println("Server Port: " + serverPort);
             } catch (Exception e) {
                 System.err.println("Failure during server initialization");
                 e.printStackTrace();
             }
 
             // Thread to allow multiple clients to connect
-            t = new Thread(() -> {
+            new Thread(() -> {
                 try {
-                    while (true) {
-                        System.err.println("Server ready on port " +
-                            serverPort);
-                        SSLSocket c = (SSLSocket)ssock.accept();
-                        clientMap.put(c.getPort(), c);
-                        try {
-                            write(c, read(c));
-                        } catch (Exception e) {
-                            System.out.println("Caught " + e.getMessage());
-                            e.printStackTrace();
-                            exceptionList.add(e);
-                        }
-                    }
+                    System.err.println("Server starting to accept");
+                    serverLatch.countDown();
+                    do {
+                        SSLSocket sock = (SSLSocket)ssock.accept();
+                        threadPool.submit(new ServerThread(sock));
+                    } while (true);
                 } catch (Exception ex) {
                     System.err.println("Server Down");
                     ex.printStackTrace();
+                } finally {
+                    threadPool.close();
                 }
-            });
-            t.start();
+            }).start();
         }
 
-        Server() {
-            this(new ServerBuilder());
-        }
+        class ServerThread extends Thread {
+            SSLSocket sock;
 
-        /**
-         * @param km - true for an empty key manager
-         * @param tm - true for an empty trust manager
-         */
-        Server(boolean km, boolean tm) {
-            super();
-            name = "server";
-            try {
-                sslContext = SSLContext.getInstance("TLS");
-                sslContext.init(TLSBase.getKeyManager(km),
-                    TLSBase.getTrustManager(tm), null);
-                fac = sslContext.getServerSocketFactory();
-                ssock = (SSLServerSocket) fac.createServerSocket(0);
-                ssock.setNeedClientAuth(true);
-                serverPort = ssock.getLocalPort();
-            } catch (Exception e) {
-                System.err.println("Failure during server initialization");
-                e.printStackTrace();
-            }
-
-                // Thread to allow multiple clients to connect
-                t = new Thread(() -> {
-                    try {
-                        while (true) {
-                            System.err.println("Server ready on port " +
-                                serverPort);
-                            SSLSocket c = (SSLSocket)ssock.accept();
-                            clientMap.put(c.getPort(), c);
-                            try {
-                                write(c, read(c));
-                            } catch (Exception e) {
-                                System.out.println("Caught " + e.getMessage());
-                                e.printStackTrace();
-                                exceptionList.add(e);
-                            }
-                        }
-                    } catch (Exception ex) {
-                        System.err.println("Server Down");
-                        ex.printStackTrace();
-                    }
-                });
-                t.start();
-            }
-
-        // Exit test to quit the test.  This must be called at the end of the
-        // test or the test will never end.
-        void done() {
-            try {
-                t.join(5000);
-                ssock.close();
-            } catch (Exception e) {
-                System.err.println(e.getMessage());
-                e.printStackTrace();
+            ServerThread(SSLSocket s) {
+                this.sock = s;
+                System.err.println("(Server) client connection on port " +
+                    sock.getPort());
+                clientMap.put(sock.getPort(), sock);
             }
-        }
 
-        // Read from the client
-        byte[] read(Client client) throws Exception {
-            SSLSocket s = clientMap.get(Integer.valueOf(client.getPort()));
-            if (s == null) {
-                System.err.println("No socket found, port " + client.getPort());
+            public void run() {
+                try {
+                    write(sock, read(sock));
+                } catch (Exception e) {
+                    System.err.println("Caught " + e.getMessage());
+                    e.printStackTrace();
+                    exceptionList.add(e);
+                }
             }
-            return read(s);
         }
 
-        // Write to the client
-        void write(Client client, byte[] data) throws Exception {
-            write(clientMap.get(client.getPort()), data);
+        Server() {
+            this(new ServerBuilder());
         }
 
-        // Server writes to the client, then reads from the client.
-        // Return true if the read & write data match, false if not.
-        boolean writeRead(Client client, String s) throws Exception{
-            write(client, s.getBytes());
-            return (Arrays.compare(s.getBytes(), client.read()) == 0);
+        public SSLSession getSession(Client client) throws Exception {
+            System.err.println("getSession("+client.getPort()+")");
+            SSLSocket clientSocket = clientMap.get(client.getPort());
+            if (clientSocket == null) {
+                throw new Exception("Server can't find client socket");
+            }
+            return clientSocket.getSession();
         }
 
-        // Get the SSLSession from the server side socket
-        SSLSession getSession(Client c) {
-            SSLSocket s = clientMap.get(Integer.valueOf(c.getPort()));
-            return s.getSession();
+        void close(Client client) {
+            try {
+                System.err.println("close("+client.getPort()+")");
+                clientMap.remove(client.getPort()).close();
+            } catch (Exception e) {
+                ;
+            }
         }
-
-        // Close client socket
-        void close(Client c) throws IOException {
-            SSLSocket s = clientMap.get(Integer.valueOf(c.getPort()));
-            s.close();
+        void close() throws InterruptedException {
+            clientMap.values().stream().forEach(s -> {
+                try {
+                    s.close();
+                } catch (IOException e) {}
+            });
+            threadPool.awaitTermination(500, TimeUnit.MILLISECONDS);
         }
 
         List getExceptionList() {
@@ -312,11 +265,11 @@ Server build() {
         }
     }
     /**
-     * Client side will establish a connection from the constructor and wait.
+     * Client side will establish a SSLContext instance.
      * It must be run after the Server constructor is called.
      */
     static class Client extends TLSBase {
-        SSLSocket sock;
+        public SSLSocket socket;
         boolean km, tm;
         Client() {
             this(false, false);
@@ -330,55 +283,70 @@ static class Client extends TLSBase {
             super();
             this.km = km;
             this.tm = tm;
-            connect();
-        }
-
-        // Connect to server.  Maybe runnable in the future
-        public SSLSocket connect() {
             try {
                 sslContext = SSLContext.getInstance("TLS");
-                sslContext.init(TLSBase.getKeyManager(km), TLSBase.getTrustManager(tm), null);
-                sock = (SSLSocket)sslContext.getSocketFactory().createSocket();
-                sock.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort));
-                System.err.println("Client connected using port " +
-                        sock.getLocalPort());
-                name = "client(" + sock.toString() + ")";
-                write("Hello");
-                read();
+                sslContext.init(TLSBase.getKeyManager(km),
+                    TLSBase.getTrustManager(tm), null);
+                socket = createSocket();
             } catch (Exception ex) {
                 ex.printStackTrace();
             }
-            return sock;
         }
 
-        // Read from the client socket
-        byte[] read() throws Exception {
-            return read(sock);
+        Client(Client cl) {
+            sslContext = cl.sslContext;
+            socket = createSocket();
         }
 
-        // Write to the client socket
-        void write(byte[] data) throws Exception {
-            write(sock, data);
+        public SSLSocket createSocket() {
+            try {
+                return (SSLSocket) sslContext.getSocketFactory().createSocket();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+            return null;
         }
-        void write(String s) throws Exception {
-            write(sock, s.getBytes());
+
+        public SSLSocket connect() {
+            try {
+                socket.connect(new InetSocketAddress(
+                    InetAddress.getLoopbackAddress(), serverPort));
+                System.err.println("Client (" +
+                    Thread.currentThread().getName() +
+                    ") connected using port " + socket.getLocalPort() + " to " +
+                    socket.getPort());
+                writeRead();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                return null;
+            }
+            return socket;
         }
 
-        // Client writes to the server, then reads from the server.
-        // Return true if the read & write data match, false if not.
-        boolean writeRead(Server server, String s) throws Exception {
-            write(s.getBytes());
-            return (Arrays.compare(s.getBytes(), server.read(this)) == 0);
+        public SSLSession getSession() {
+            return socket.getSession();
+        }
+        public void close() {
+            try {
+                socket.close();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
         }
 
-        // Get port from the socket
-        int getPort() {
-            return sock.getLocalPort();
+        public int getPort() {
+            return socket.getLocalPort();
         }
 
-        // Close socket
-        void close() throws IOException {
-            sock.close();
+        private SSLSocket writeRead() {
+            try {
+                write(socket, "Hello".getBytes(StandardCharsets.ISO_8859_1));
+                read(socket);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+            return socket;
         }
+
     }
 }
diff --git a/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java b/test/jdk/javax/swing/ButtonGroup/TestButtonGroupFocusTraversal.java
index c115d44edbf7..4780c10e3a5f 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((x) -> toggleButtonActionPerformed = true);
+                toggleButton2.addActionListener((x) -> toggleButtonActionPerformed = true);
+
+                checkBox1.addActionListener((x) -> checkboxActionPerformed = true);
+                checkBox2.addActionListener((x) -> 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/JColorChooser/Test8152419.java b/test/jdk/javax/swing/JColorChooser/Test8152419.java
index 65615acbdee3..48067a4d2bad 100644
--- a/test/jdk/javax/swing/JColorChooser/Test8152419.java
+++ b/test/jdk/javax/swing/JColorChooser/Test8152419.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 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
@@ -21,11 +21,12 @@
  * questions.
  */
 
- /*
-* @test
-* @bug 8152419
-* @summary To Verify JColorChooser tab selection
-* @run main/manual Test8152419
+/*
+ * @test
+ * @bug 8152419
+ * @library /test/lib
+ * @summary To Verify JColorChooser tab selection
+ * @run main/manual Test8152419
  */
 
 import java.awt.Color;
@@ -43,9 +44,17 @@
 import javax.swing.UIManager;
 import javax.swing.border.EmptyBorder;
 
+import jtreg.SkippedException;
+
 public class Test8152419 {
 
     public static void main(String args[]) throws Exception {
+        // ColorChooser UI design is different for GTK L&F.
+        // There are no tabs available for GTK L&F, skip the testing.
+        if (UIManager.getLookAndFeel().getName().contains("GTK")) {
+            throw new SkippedException("Test not applicable for GTK L&F");
+        }
+
         final CountDownLatch latch = new CountDownLatch(1);
 
         JColorChooserTest test = new JColorChooserTest(latch);
diff --git a/test/jdk/javax/swing/JComboBox/ComboPopupBug.java b/test/jdk/javax/swing/JComboBox/ComboPopupBug.java
index 8c9dcde7d657..97074caba14e 100644
--- a/test/jdk/javax/swing/JComboBox/ComboPopupBug.java
+++ b/test/jdk/javax/swing/JComboBox/ComboPopupBug.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
@@ -21,66 +21,81 @@
  * questions.
  */
 
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
 
 /*
  * @test
  * @bug 8322754
+ * @key headful
  * @summary Verifies clicking JComboBox during frame closure causes Exception
- * @library /java/awt/regtesthelpers
- * @build PassFailJFrame
- * @run main/manual ComboPopupBug
+ * @run main ComboPopupBug
  */
 
 public class ComboPopupBug {
-    private static final String instructionsText = """
-            This test is used to verify that clicking on JComboBox
-            when frame containing it is about to close should not
-            cause IllegalStateException.
-
-            A JComboBox is shown with Close button at the bottom.
-            Click on Close and then click on JComboBox arrow button
-            to try to show combobox popup.
-            If IllegalStateException is thrown, test will automatically Fail
-            otherwise click Pass.""";
+    private static JFrame frame;
+    private static JButton closeButton;
+    private static JComboBox comboBox;
+    private static Robot robot;
+    private static final int PADDING = 10;
 
     public static void main(String[] args) throws Exception {
-        PassFailJFrame.builder()
-                .title("ComboPopup Instructions")
-                .instructions(instructionsText)
-                .testTimeOut(5)
-                .rows(10)
-                .columns(35)
-                .testUI(ComboPopupBug::createUI)
-                .build()
-                .awaitAndCheck();
+        try {
+            robot = new Robot();
+            robot.setAutoDelay(50);
+
+            SwingUtilities.invokeAndWait(ComboPopupBug::createUI);
+
+            robot.waitForIdle();
+            robot.delay(1000);
+
+            SwingUtilities.invokeAndWait(() -> closeButton.doClick());
+
+            robot.waitForIdle();
+        } finally {
+            SwingUtilities.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
     }
 
-    private static JFrame createUI() {
-        JFrame frame = new JFrame("ComboPopup");
+    private static void clickComboBox() {
+        Point comboBoxLocation = comboBox.getLocationOnScreen();
+        Dimension comboBoxSize = comboBox.getSize();
 
-        JComboBox cb = new JComboBox<>();
-        cb.setEditable(true);
-        cb.addItem("test");
-        cb.addItem("test2");
-        cb.addItem("test3");
+        robot.mouseMove(comboBoxLocation.x + comboBoxSize.width - PADDING,
+                comboBoxLocation.y + comboBoxSize.height / 2);
+        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+    }
 
-        JButton b = new JButton("Close");
-        b.addActionListener(
-                (e)->{
-                    try {
-                        Thread.sleep(3000);
-                    } catch (Exception ignored) {
-                    }
-                    frame.setVisible(false);
-                });
+    private static void createUI() {
+        frame = new JFrame("ComboPopup");
 
-        frame.getContentPane().add(cb, "North");
-        frame.getContentPane().add(b, "South");
-        frame.setSize(200, 200);
+        comboBox = new JComboBox<>();
+        comboBox.setEditable(true);
+        comboBox.addItem("test");
+        comboBox.addItem("test2");
+        comboBox.addItem("test3");
 
-        return frame;
+        closeButton = new JButton("Close");
+        closeButton.addActionListener((e) -> {
+            clickComboBox();
+            frame.setVisible(false);
+        });
+
+        frame.getContentPane().add(comboBox, "North");
+        frame.getContentPane().add(closeButton, "South");
+        frame.setSize(200, 200);
+        frame.setLocationRelativeTo(null);
+        frame.setVisible(true);
     }
 }
diff --git a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java
index 57ee1a2bb3ff..c7a6b53d4f4a 100644
--- a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java
+++ b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -135,6 +135,10 @@ public static void main(String[] args) throws Exception {
             if (laf.getClassName().contains("Motif")) {
                 System.out.println("Skipping Motif L&F as it is deprecated");
                 continue;
+            } else if (laf.getClassName().contains("GTK")) {
+                System.out.println("GTK doesn't support color setting explicitly" +
+                        " specified by user using UIManager property.");
+                continue;
             }
             System.out.println("Testing L&F: " + laf.getClassName());
             SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
diff --git a/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java b/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java
new file mode 100644
index 000000000000..fddfbb28384d
--- /dev/null
+++ b/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.plaf.nimbus.NimbusLookAndFeel;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/*
+ * @test
+ * @bug 4248210
+ * @key headful
+ * @summary Tests that HTML in JLabel is painted using LAF-defined
+            foreground color
+ * @run main bug4248210
+ */
+
+public class bug4248210 {
+    private static final Color labelColor = Color.red;
+
+    public static void main(String[] args) throws Exception {
+        for (UIManager.LookAndFeelInfo laf :
+                UIManager.getInstalledLookAndFeels()) {
+            if (!(laf.getName().contains("Motif") || laf.getName().contains("GTK"))) {
+                System.out.println("Testing LAF: " + laf.getName());
+                SwingUtilities.invokeAndWait(() -> test(laf));
+            }
+        }
+    }
+
+    private static void test(UIManager.LookAndFeelInfo laf) {
+        setLookAndFeel(laf);
+        if (UIManager.getLookAndFeel() instanceof NimbusLookAndFeel) {
+            // reset "basic" properties
+            UIManager.getDefaults().put("Label.foreground", null);
+            // set "synth - nimbus" properties
+            UIManager.getDefaults().put("Label[Enabled].textForeground", labelColor);
+        } else {
+            // reset "synth - nimbus" properties
+            UIManager.getDefaults().put("Label[Enabled].textForeground", null);
+            // set "basic" properties
+            UIManager.getDefaults().put("Label.foreground", labelColor);
+        }
+
+        JLabel label = new JLabel("Can You Read This?");
+        label.setSize(150, 30);
+
+        BufferedImage img = paintToImage(label);
+        if (!chkImgForegroundColor(img)) {
+            try {
+                ImageIO.write(img, "png", new File("Label_" + laf.getName() + ".png"));
+            } catch (IOException ignored) {}
+            throw new RuntimeException("JLabel not painted with LAF defined " +
+                    "foreground color");
+        }
+        System.out.println("Test Passed");
+    }
+
+    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 BufferedImage paintToImage(JComponent content) {
+        BufferedImage im = new BufferedImage(content.getWidth(), content.getHeight(),
+                TYPE_INT_RGB);
+        Graphics2D g = (Graphics2D) im.getGraphics();
+        g.setBackground(Color.WHITE);
+        g.clearRect(0, 0, content.getWidth(), content.getHeight());
+        content.paint(g);
+        g.dispose();
+        return im;
+    }
+
+    private static boolean chkImgForegroundColor(BufferedImage img) {
+        for (int x = 0; x < img.getWidth(); ++x) {
+            for (int y = 0; y < img.getHeight(); ++y) {
+                if (img.getRGB(x, y) == labelColor.getRGB()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/test/jdk/javax/swing/regtesthelpers/Util.java b/test/jdk/javax/swing/regtesthelpers/Util.java
index 4724fa200d60..3f043d1b7c0e 100644
--- a/test/jdk/javax/swing/regtesthelpers/Util.java
+++ b/test/jdk/javax/swing/regtesthelpers/Util.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, 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 predicate) { + for (Component child : container.getComponents()) { + if (predicate.test(child)) { + return child; + } + if (child instanceof Container cont && cont.getComponentCount() > 0) { + Component result = findComponentImpl(cont, predicate); + if (result != null) { + return result; } } } - return null; } diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java index c6b943708071..82e69da79479 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -51,19 +51,6 @@ public class TestDockerMemoryMetricsSubgroup { DockerfileConfig.getBaseImageName() + ":" + DockerfileConfig.getBaseImageVersion(); - 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) { @@ -77,7 +64,7 @@ public static void main(String[] args) throws Exception { ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); - if (isRootless()) { + if (DockerTestUtils.isRootless()) { throw new SkippedException("Test skipped in rootless mode"); } diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index b6b936078c97..4037b03195ad 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -94,6 +94,9 @@ public static void main(String[] args) { if (Platform.isPPC()) { COMPILATION_TIMEOUT = COMPILATION_TIMEOUT * 2; } + if (Platform.isDebugBuild()) { + COMPILATION_TIMEOUT = COMPILATION_TIMEOUT * 2; + } warmup(); for (int compileLevel : new int[]{4}) { for (boolean compileRun : new boolean[]{true}) { diff --git a/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java b/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java new file mode 100644 index 000000000000..fbef91e73aa0 --- /dev/null +++ b/test/jdk/jdk/jfr/event/runtime/TestBackToBackSensitive.java @@ -0,0 +1,132 @@ +/* + * 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. + */ +package jdk.jfr.event.runtime; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.StackTrace; +import jdk.jfr.consumer.EventStream; +import jdk.jfr.consumer.RecordedClassLoader; +import jdk.test.lib.jfr.TestClassLoader; + +/** + * @test + * @summary The test verifies that jdk.ClassLoaderStatistics and + * jdk.ThreadThreadDump are not emitted at the beginning of a chunk + * when the period is everyChunk, as is the case in default.jfc + * @requires vm.flagless + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.event.runtime.TestBackToBackSensitive + */ +public class TestBackToBackSensitive { + @StackTrace(false) + static class FillEvent extends Event { + String message; + } + public static Object OBJECT; + + public static void main(String... arg) throws Exception { + TestClassLoader loader = new TestClassLoader(); + Class clazz = loader.loadClass(TestBackToBackSensitive.class.getName()); + String classLoaderName = loader.getClass().getName(); + OBJECT = clazz.getDeclaredConstructor().newInstance(); + Configuration configuration = Configuration.getConfiguration("default"); + try (Recording r1 = new Recording(configuration)) { + // Start chunk 1 + r1.start(); + try (Recording r2 = new Recording()) { + // Start chunk 2 + r2.start(); + // Starts chunk 3 + r2.stop(); + } + // Start chunk 4 by filling up chunk 3 + for (int i = 0; i < 1_500_000; i++) { + FillEvent f = new FillEvent(); + f.commit(); + } + r1.stop(); + Path file = Path.of("file.jfr"); + r1.dump(file); + Set threadDumps = new LinkedHashSet<>(); + Set classLoaderStatistics = new LinkedHashSet<>(); + Set physicalMemory = new LinkedHashSet<>(); + try (EventStream es = EventStream.openFile(file)) { + es.onEvent("jdk.ThreadDump", e -> threadDumps.add(e.getStartTime())); + es.onEvent("jdk.ClassLoaderStatistics", e -> { + RecordedClassLoader cl = e.getValue("classLoader"); + if (cl != null) { + if (cl.getType().getName().equals(classLoaderName)) { + classLoaderStatistics.add(e.getStartTime()); + System.out.println("Class loader" + e); + } + } + }); + es.onEvent("jdk.PhysicalMemory", e -> physicalMemory.add(e.getStartTime())); + es.start(); + } + long chunkFiles = filesInRepository(); + System.out.println("Number of chunk files: " + chunkFiles); + // When jdk.PhysicalMemory is expected to be emitted: + // Chunk 1: begin, end + // Chunk 2: begin, end + // Chunk 3: begin, end + // Chunk 4: begin, end + assertCount("jdk.PhysicalMemory", physicalMemory, 2 * chunkFiles); + // When jdk.ClassLoaderStatistics and jdk.ThreadThreadDump are expected to be + // emitted: + // Chunk 1: begin, end + // Chunk 2: begin, end + // Chunk 3: end + // Chunk 4: end + assertCount("jdk.ThreadDump", threadDumps, 2 + 2 + (chunkFiles - 2)); + assertCount("jdk.ClassLoaderStatistics", classLoaderStatistics, 2 + 2 + (chunkFiles - 2)); + } + } + + private static long filesInRepository() throws IOException { + Path repository = Path.of(System.getProperty("jdk.jfr.repository")); + return Files.list(repository).filter(p -> p.toString().endsWith(".jfr")).count(); + } + + private static void assertCount(String eventName, Set timestamps, long expected) throws Exception { + System.out.println("Timestamps for " + eventName + ":"); + for (Instant timestamp : timestamps) { + System.out.println(timestamp); + } + int count = timestamps.size(); + if (count != expected) { + throw new Exception("Expected " + expected + " timestamps for event " + eventName + ", but got " + count); + } + } +} diff --git a/test/jdk/jdk/nio/zipfs/TestPosix.java b/test/jdk/jdk/nio/zipfs/TestPosix.java index f629dfef2225..0a2942e1e793 100644 --- a/test/jdk/jdk/nio/zipfs/TestPosix.java +++ b/test/jdk/jdk/nio/zipfs/TestPosix.java @@ -66,7 +66,7 @@ import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; -/** +/* * @test * @bug 8213031 8273935 * @summary Test POSIX ZIP file operations. @@ -697,7 +697,7 @@ public void testJarFile() throws IOException { delTree(UNZIP_DIR); Files.createDirectory(UNZIP_DIR); File targetDir = UNZIP_DIR.toFile(); - try (JarFile jf = new JarFile(ZIP_FILE.toFile())) { + try (JarFile jf = new JarFile(JAR_FILE.toFile())) { Enumeration zenum = jf.entries(); while (zenum.hasMoreElements()) { JarEntry ze = zenum.nextElement(); diff --git a/test/jdk/sun/java2d/marlin/ClipShapeTest.java b/test/jdk/sun/java2d/marlin/ClipShapeTest.java index 3bdbd416e63d..e77fca6924d9 100644 --- a/test/jdk/sun/java2d/marlin/ClipShapeTest.java +++ b/test/jdk/sun/java2d/marlin/ClipShapeTest.java @@ -154,13 +154,12 @@ static enum ShapeMode { static final AtomicBoolean isMarlin = new AtomicBoolean(); static final AtomicBoolean isClipRuntime = new AtomicBoolean(); + static final Logger log = Logger.getLogger("sun.java2d.marlin"); + static { Locale.setDefault(Locale.US); // FIRST: Get Marlin runtime state from its log: - - // initialize j.u.l Looger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { diff --git a/test/jdk/sun/security/krb5/NullStringToKey.java b/test/jdk/sun/security/krb5/NullStringToKey.java new file mode 100644 index 000000000000..ca6b6d5439e6 --- /dev/null +++ b/test/jdk/sun/security/krb5/NullStringToKey.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8343622 + * @summary KerberosKey created with null key bytes + * @run main/othervm NullStringToKey + */ + +import javax.security.auth.kerberos.KerberosKey; +import javax.security.auth.kerberos.KerberosPrincipal; +import java.security.Security; +import java.util.List; + +public class NullStringToKey { + public static void main(String[] args) throws Exception { + + Security.removeProvider("SUN"); + Security.removeProvider("SunJCE"); + + var name = new KerberosPrincipal("me@ME.COM"); + var pass = "password".toCharArray(); + for (var alg : List.of( + "aes128-cts-hmac-sha1-96", "aes256-cts-hmac-sha1-96", + "aes128-cts-hmac-sha256-128", "aes256-cts-hmac-sha384-192")) { + System.out.println(alg); + // Do not use Utils.runAndCheckException as it might call + // MessageDigest.getInstance("MD5") at class initialization + // and we have already removed the SUN provider. + try { + new KerberosKey(name, pass, alg); + throw new RuntimeException("Didn't get expected exception"); + } catch (IllegalArgumentException e) { + // expected + System.out.println(e); + } + } + } +} diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java b/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java new file mode 100644 index 000000000000..d526b02fac0a --- /dev/null +++ b/test/jdk/sun/security/pkcs11/Cipher/TestDisabledAlgorithms.java @@ -0,0 +1,81 @@ +/* + * 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 sm CiPhEr.RSA/ECB/PKCS1Padding true + * @run main/othervm TestDisabledAlgorithms sm cIpHeR.rsA true + * @run main/othervm TestDisabledAlgorithms sm Cipher.what false + * @run main/othervm TestDisabledAlgorithms sm CiPhER.RSA/ECB/PKCS1Padding2 false + */ +import java.util.List; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import jdk.test.lib.Utils; + +public class TestDisabledAlgorithms extends PKCS11Test { + + boolean shouldThrow; + + TestDisabledAlgorithms(boolean shouldThrow) { + this.shouldThrow = shouldThrow; + } + + private static final String PROP_NAME = "jdk.crypto.disabledAlgorithms"; + + private static void test(String alg, Provider p, boolean shouldThrow) + throws Exception { + System.out.println("Testing " + p.getName() + ": " + alg + + ", shouldThrow=" + shouldThrow); + if (shouldThrow) { + Utils.runAndCheckException(() -> Cipher.getInstance(alg, p), + NoSuchAlgorithmException.class); + } else { + Cipher c = Cipher.getInstance(alg, p); + System.out.println("Got cipher w/ algo " + c.getAlgorithm()); + } + } + + @Override + public void main(Provider p) throws Exception { + for (String a : List.of("RSA/ECB/PKCS1Padding", "RSA")) { + test(a, p, shouldThrow); + } + System.out.println("Done"); + } + + public static void main(String[] args) throws Exception { + String propValue = args[1]; + System.out.println("Setting Security Prop " + PROP_NAME + " = " + + propValue); + Security.setProperty(PROP_NAME, propValue); + boolean shouldThrow = Boolean.valueOf(args[2]); + main(new TestDisabledAlgorithms(shouldThrow), args); + } +} diff --git a/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java b/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java new file mode 100644 index 000000000000..8274602c09f6 --- /dev/null +++ b/test/jdk/sun/security/pkcs11/Signature/TestNONEwithRSA.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.security.*; +import java.security.interfaces.*; +import java.security.spec.*; +import java.util.stream.IntStream; +import jtreg.SkippedException; + +/** + * @test + * @bug 8244336 + * @summary Test the NONEwithRSA signature refactoring for JCE layer + * algorithm restriction + * @library /test/lib .. + * @modules jdk.crypto.cryptoki + */ +public class TestNONEwithRSA extends PKCS11Test { + + private static final String SIGALG = "NONEwithRSA"; + + private static final int[] KEYSIZES = { 2048, 3072 }; + private static final byte[] DATA = generateData(100); + + public static void main(String[] args) throws Exception { + main(new TestNONEwithRSA(), args); + } + + @Override + public void main(Provider p) throws Exception { + try { + Signature.getInstance(SIGALG, p); + } catch (NoSuchAlgorithmException nsae) { + throw new SkippedException("Skip due to no support for " + SIGALG); + } + + for (int kSize : KEYSIZES) { + System.out.println("[KEYSIZE = " + kSize + "]"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p); + kpg.initialize(kSize); + KeyPair kp = kpg.generateKeyPair(); + PrivateKey privKey = kp.getPrivate(); + PublicKey pubKey = kp.getPublic(); + checkSignature(p, DATA, pubKey, privKey); + } + } + + private static void checkSignature(Provider p, byte[] data, PublicKey pub, + PrivateKey priv) + throws NoSuchAlgorithmException, InvalidKeyException, + SignatureException, NoSuchProviderException, + InvalidAlgorithmParameterException { + + Signature sig = Signature.getInstance(SIGALG, p); + sig.initSign(priv); + + sig.update(data); + byte[] signedData = sig.sign(); + + // Make sure signature verifies with original data + sig.initVerify(pub); + sig.update(data); + if (!sig.verify(signedData)) { + throw new RuntimeException("Failed to verify signature"); + } + + // Make sure signature does NOT verify when the original data + // has changed + sig.initVerify(pub); + sig.update(data); + sig.update(data); + if (sig.verify(signedData)) { + throw new RuntimeException("Failed to detect bad signature"); + } + System.out.println(" => Passed"); + } +} diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTClient.java b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTClient.java new file mode 100644 index 000000000000..02d291ff154a --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTClient.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /test/lib + * @library /javax/net/ssl/templates + * @bug 8242008 + * @summary Verifies multiple PSKs are used by JSSE + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.newSessionTicketCount=1 + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.newSessionTicketCount=3 + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.newSessionTicketCount=10 + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=true + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=false + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=false + * @run main/othervm MultiNSTClient -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import javax.net.ssl.SSLSession; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.List; + +/** + * This test verifies that multiple NSTs and PSKs are sent by a JSSE server. + * Then JSSE client is able to store them all and resume the connection. It + * requires specific text in the TLS debugging to verify the success. + */ + +public class MultiNSTClient { + + static HexFormat hex = HexFormat.of(); + + public static void main(String[] args) throws Exception { + + if (!args[0].equalsIgnoreCase("p")) { + StringBuilder sb = new StringBuilder(); + Arrays.stream(args).forEach(a -> { + sb.append(a); + sb.append(" "); + }); + String params = sb.toString(); + System.setProperty("test.java.opts", + "-Dtest.src=" + System.getProperty("test.src") + + " -Dtest.jdk=" + System.getProperty("test.jdk") + + " -Dtest.root=" + System.getProperty("test.root") + + " -Djavax.net.debug=ssl,handshake " + params + ); + + boolean TLS13 = args[0].contains("1.3"); + + System.out.println("test.java.opts: " + + System.getProperty("test.java.opts")); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + Utils.addTestJavaOpts("MultiNSTClient", "p")); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + boolean pass = true; + try { + List list = output.stderrShouldContain("MultiNST PSK"). + asLines().stream().filter(s -> + s.contains("MultiNST PSK")).toList(); + List serverPSK = list.stream().filter(s -> + s.contains("MultiNST PSK (Server)")).toList(); + List clientPSK = list.stream().filter(s -> + s.contains("MultiNST PSK (Client)")).toList(); + System.out.println("found list: " + list.size()); + System.out.println("found server: " + serverPSK.size()); + serverPSK.stream().forEach(s -> System.out.println("\t" + s)); + System.out.println("found client: " + clientPSK.size()); + clientPSK.stream().forEach(s -> System.out.println("\t" + s)); + for (int i = 0; i < 2; i++) { + String svr = serverPSK.getFirst(); + String cli = clientPSK.getFirst(); + if (svr.regionMatches(svr.length() - 16, cli, + cli.length() - 16, 16)) { + System.out.println("entry " + (i + 1) + " match."); + } else { + System.out.println("entry " + (i + 1) + + " server and client PSK didn't match:"); + System.out.println(" server: " + svr); + System.out.println(" client: " + cli); + pass = false; + } + } + } catch (RuntimeException e) { + System.out.println("No MultiNST PSK found."); + pass = false; + } + + if (TLS13) { + if (!pass) { + throw new Exception("Test failed: " + params); + } + } else { + if (pass) { + throw new Exception("Test failed: " + params); + } + } + System.out.println("Test Passed"); + return; + } + + TLSBase.Server server = new TLSBase.Server(); + server.serverLatch.await(); + System.out.println("------ Server ready, starting original client."); + TLSBase.Client initial = new TLSBase.Client(); + SSLSession initialSession = initial.connect().getSession(); + System.out.println("id = " + hex.formatHex(initialSession.getId())); + System.out.println("session = " + initialSession); + + System.out.println("------ getNewSession from original client"); + TLSBase.Client resumClient = new TLSBase.Client(initial); + SSLSession resumption = resumClient.connect().getSession(); + System.out.println("id = " + hex.formatHex(resumption.getId())); + System.out.println("session = " + resumption); + if (!initialSession.toString().equalsIgnoreCase(resumption.toString())) { + throw new Exception("Resumed session did not match"); + } + + System.out.println("------ Second getNewSession from original client"); + TLSBase.Client resumClient2 = new TLSBase.Client(initial); + resumption = resumClient2.connect().getSession(); + System.out.println("id = " + hex.formatHex(resumption.getId())); + System.out.println("session = " + resumption); + if (!initialSession.toString().equalsIgnoreCase(resumption.toString())) { + throw new Exception("Resumed session did not match"); + } + + System.out.println("------ New client connection"); + TLSBase.Client newConnection = new TLSBase.Client(); + SSLSession newSession = newConnection.connect().getSession(); + System.out.println("id = " + hex.formatHex(newSession.getId())); + System.out.println("session = " + newSession); + if (initialSession.toString().equalsIgnoreCase(newSession.toString())) { + throw new Exception("new session is the same as the initial."); + } + + System.out.println("------ Closing connections"); + initial.close(); + resumClient.close(); + resumClient2.close(); + newConnection.close(); + server.close(); + System.out.println("------ End"); + System.exit(0); + } +} diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTNoSessionCreation.java b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTNoSessionCreation.java new file mode 100644 index 000000000000..bced996ccc7c --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTNoSessionCreation.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /test/lib + * @library /javax/net/ssl/templates + * @bug 8242008 + * @summary Verifies resumption fails with 0 NSTs and session creation off + * @run main/othervm MultiNSTNoSessionCreation -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.newSessionTicketCount=0 + * @run main/othervm MultiNSTNoSessionCreation -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.newSessionTicketCount=0 + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.util.Arrays; + +/** + * With no NSTs sent by the server, try to resume the session with + * setEnabledSessionCreation(false). The test should get an exception and + * fail to connect. + */ + +public class MultiNSTNoSessionCreation { + + public static void main(String[] args) throws Exception { + + if (!args[0].equalsIgnoreCase("p")) { + StringBuilder sb = new StringBuilder(); + Arrays.stream(args).forEach(a -> sb.append(a).append(" ")); + String params = sb.toString(); + System.setProperty("test.java.opts", + "-Dtest.src=" + System.getProperty("test.src") + + " -Dtest.jdk=" + System.getProperty("test.jdk") + + " -Dtest.root=" + System.getProperty("test.root") + + " -Djavax.net.debug=ssl,handshake " + params); + + System.out.println("test.java.opts: " + + System.getProperty("test.java.opts")); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + Utils.addTestJavaOpts("MultiNSTNoSessionCreation", "p")); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + try { + if (output.stderrContains( + "(PROTOCOL_VERSION): New session creation is disabled")) { + return; + } + } catch (RuntimeException e) { + throw new Exception("Error collecting data", e); + } + throw new Exception("Disabled creation msg not found"); + } + + TLSBase.Server server = new TLSBase.Server(); + server.serverLatch.await(); + System.out.println("------ Server ready, starting initial client."); + TLSBase.Client initial = new TLSBase.Client(); + initial.connect(); + System.out.println( + "------ Resume client w/ setEnableSessionCreation set to false"); + TLSBase.Client resumClient = new TLSBase.Client(initial); + resumClient.socket.setEnableSessionCreation(false); + resumClient.connect(); + + System.out.println("------ Closing connections"); + initial.close(); + resumClient.close(); + server.close(); + System.out.println("------ End"); + System.exit(0); + } +} diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTParallel.java b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTParallel.java new file mode 100644 index 000000000000..ae6da829f22e --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTParallel.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /test/lib + * @library /javax/net/ssl/templates + * @bug 8242008 + * @summary Verifies multiple PSKs are used by TLSv1.3 + * @run main/othervm MultiNSTParallel 10 -Djdk.tls.client.protocols=TLSv1.3 + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import javax.net.ssl.SSLSession; +import java.util.ArrayList; +import java.util.HexFormat; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +/** + * This test verifies that parallel resumption connections successfully get + * a PSK entry and not initiate a full handshake. + * + * Note: THe first argument after 'MultiNSTParallel' is the ticket count + * The test will set 'jdk.tls.server.NewSessionTicketCount` to that number and + * will start the same number of resumption client attempts. The ticket count + * must be the same or larger than resumption attempts otherwise the queue runs + * empty and the test will fail. + * + * Because this test runs parallel connections, the thread order finish is not + * guaranteed. Each client NST id is checked with all server NSTs ids until + * a match is found. When a match is found, it is removed from the list to + * verify no NST was used more than once. + * + * TLS 1.2 spec does not specify multiple NST behavior. + */ + +public class MultiNSTParallel { + + static HexFormat hex = HexFormat.of(); + final static CountDownLatch wait = new CountDownLatch(1); + + static class ClientThread extends Thread { + TLSBase.Client client; + + ClientThread(TLSBase.Client c) { + client = c; + } + + public void run() { + String name = Thread.currentThread().getName(); + SSLSession r; + System.err.println(name + " is ready"); + try { + wait.await(); + r = new TLSBase.Client(client).connect().getSession(); + } catch (Exception e) { + throw new RuntimeException(name + ": " +e); + } + StringBuffer sb = new StringBuffer(100); + sb.append("(").append(name).append(") id = "); + sb.append(hex.formatHex(r.getId())); + sb.append("\n(").append(name).append(") session = ").append(r); + System.err.println(sb); + if (!client.getSession().toString().equalsIgnoreCase(r.toString())) { + throw new RuntimeException("(" + name + + ") Resumed session did not match"); + } + } + } + + static boolean pass = true; + + public static void main(String[] args) throws Exception { + + if (!args[0].equalsIgnoreCase("p")) { + int ticketCount = Integer.parseInt(args[0]); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < args.length; i++) { + sb.append(" ").append(args[i]); + } + String params = sb.toString(); + System.setProperty("test.java.opts", + "-Dtest.src=" + System.getProperty("test.src") + + " -Dtest.jdk=" + System.getProperty("test.jdk") + + " -Dtest.root=" + System.getProperty("test.root") + + " -Djavax.net.debug=ssl,handshake " + + " -Djdk.tls.server.newSessionTicketCount=" + ticketCount + + params); + + boolean TLS13 = args[1].contains("1.3"); + + System.out.println("test.java.opts: " + + System.getProperty("test.java.opts")); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + Utils.addTestJavaOpts("MultiNSTParallel", "p")); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + try { + List list = output.stderrShouldContain("MultiNST PSK"). + asLines().stream().filter(s -> + s.contains("MultiNST PSK")).toList(); + List sp = list.stream().filter(s -> + s.contains("MultiNST PSK (Server)")).toList(); + List serverPSK = new ArrayList<>(sp.stream().toList()); + List clientPSK = list.stream().filter(s -> + s.contains("MultiNST PSK (Client)")).toList(); + System.out.println("found list: " + list.size()); + System.out.println("found server: " + serverPSK.size()); + serverPSK.stream().forEach(s -> System.out.println("\t" + s)); + System.out.println("found client: " + clientPSK.size()); + clientPSK.stream().forEach(s -> System.out.println("\t" + s)); + if (list.size() == 0 || serverPSK.size() == 0) { + throw new Exception("Error setting up test. No server " + + "PSKs found in debug log."); + } + if (clientPSK.size() == 0) { + throw new Exception("Error setting up test. No " + + "client PSKs found in debug log."); + } + // Must search all results as order is not guaranteed. + clientPSK.stream().forEach(cli -> { + for (int i = 0; i < serverPSK.size(); i++) { + String svr = serverPSK.get(i); + if (svr.regionMatches(svr.length() - 16, cli, + cli.length() - 16, 16)) { + System.out.println("entry " + (i + 1) + " match."); + serverPSK.remove(i); + return; + } + } + System.out.println("client entry (" + cli.substring(0, 16) + + ") not found in server list"); + pass = false; + }); + } catch (RuntimeException e) { + System.out.println("Error looking at PSK results."); + throw new Exception(e); + } + + if (TLS13) { + if (!pass) { + throw new Exception("Test failed: " + params); + } + } else { + if (pass) { + throw new Exception("Test failed: " + params); + } + } + System.out.println("Test Passed"); + return; + } + + int ticketCount = Integer.parseInt( + System.getProperty("jdk.tls.server.newSessionTicketCount")); + + TLSBase.Server server = new TLSBase.Server(); + server.serverLatch.await(); + System.out.println("------ Server ready, starting initial client."); + TLSBase.Client initialClient = new TLSBase.Client(); + SSLSession initialSession = initialClient.connect().getSession(); + System.out.println("id = " + hex.formatHex(initialSession.getId())); + System.out.println("session = " + initialSession); + System.out.println("------ Initial client context ready."); + + ArrayList slist = new ArrayList<>(ticketCount); + + System.out.println("Client count = " + ticketCount); + for (int i = 0; ticketCount > i; i++) { + Thread t = new ClientThread(initialClient); + t.setName("client " + i); + slist.add(t); + t.start(); + } + + wait.countDown(); + for (Thread t : slist) { + t.join(1000); + System.err.println("released: " + t.getName()); + } + + System.out.println("------ Closing connections"); + initialClient.close(); + server.close(); + System.out.println("------ End"); + System.exit(0); + } +} diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTSequence.java b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTSequence.java new file mode 100644 index 000000000000..791ac625bd52 --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/MultiNSTSequence.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /test/lib + * @library /javax/net/ssl/templates + * @bug 8242008 + * @summary Verifies sequence of used NST entries from the cache queue. + * @run main/othervm MultiNSTSequence -Djdk.tls.server.newSessionTicketCount=2 + */ + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import javax.net.ssl.SSLSession; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.List; + +/** + * This test verifies that multiple NSTs take the oldest PSK from the + * QueueCacheEntry stored in the TLS Session Cache. + * + * Note: Beyond 9 iterations the PSK id verification code becomes complicated + * with a QueueCacheEntry limit set to retain only the 10 newest entries. + * + * TLS 1.2 spec does not specify multiple NST behavior. + */ + +public class MultiNSTSequence { + + static HexFormat hex = HexFormat.of(); + static final int ITERATIONS = 9; + + public static void main(String[] args) throws Exception { + + if (!args[0].equalsIgnoreCase("p")) { + StringBuilder sb = new StringBuilder(); + Arrays.stream(args).forEach(a -> sb.append(a).append(" ")); + String params = sb.toString(); + System.setProperty("test.java.opts", + "-Dtest.src=" + System.getProperty("test.src") + + " -Dtest.jdk=" + System.getProperty("test.jdk") + + " -Dtest.root=" + System.getProperty("test.root") + + " -Djavax.net.debug=ssl,handshake " + params); + + System.out.println("test.java.opts: " + + System.getProperty("test.java.opts")); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + Utils.addTestJavaOpts("MultiNSTSequence", "p")); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + boolean pass = true; + try { + List list = output.stderrShouldContain("MultiNST PSK"). + asLines().stream().filter(s -> + s.contains("MultiNST PSK")).toList(); + List serverPSK = list.stream().filter(s -> + s.contains("MultiNST PSK (Server)")).toList(); + List clientPSK = list.stream().filter(s -> + s.contains("MultiNST PSK (Client)")).toList(); + System.out.println("found list: " + list.size()); + System.out.println("found server: " + serverPSK.size()); + serverPSK.stream().forEach(s -> System.out.println("\t" + s)); + System.out.println("found client: " + clientPSK.size()); + clientPSK.stream().forEach(s -> System.out.println("\t" + s)); + int i; + for (i = 0; i < ITERATIONS; i++) { + String svr = serverPSK.get(i); + String cli = clientPSK.get(i); + if (svr.regionMatches(svr.length() - 16, cli, cli.length() - 16, 16)) { + System.out.println("entry " + (i + 1) + " match."); + } else { + System.out.println("entry " + (i + 1) + " server and client PSK didn't match:"); + System.out.println(" server: " + svr); + System.out.println(" client: " + cli); + pass = false; + } + } + } catch (RuntimeException e) { + System.out.println("Server and Client PSK usage order is not" + + " the same."); + pass = false; + } + + if (!pass) { + throw new Exception("Test failed: " + params); + } + System.out.println("Test Passed"); + return; + } + + TLSBase.Server server = new TLSBase.Server(); + server.serverLatch.await(); + System.out.println("------ Server ready, starting initial client."); + TLSBase.Client initial = new TLSBase.Client(); + + SSLSession initialSession = initial.connect().getSession(); + System.out.println("id = " + hex.formatHex(initialSession.getId())); + System.out.println("session = " + initialSession); + + System.out.println("------ Resume client"); + for (int i = 0; i < ITERATIONS; i++) { + SSLSession r = new TLSBase.Client(initial).connect().getSession(); + StringBuilder sb = new StringBuilder(100); + sb.append("Iteration: ").append(i); + sb.append("\tid = ").append(hex.formatHex(r.getId())); + sb.append("\tsession = ").append(r); + System.out.println(sb); + if (!initialSession.toString().equalsIgnoreCase(r.toString())) { + throw new Exception("Resumed session did not match"); + } + } + + System.out.println("------ Closing connections"); + initial.close(); + server.close(); + System.out.println("------ End"); + System.exit(0); + } +} diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java index e2885e387790..851aa5af59c2 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8206929 8212885 + * @bug 8206929 8212885 8333857 * @summary ensure that client only resumes a session if certain properties * of the session are compatible with the new connection * @library /javax/net/ssl/templates @@ -47,6 +47,9 @@ import java.security.*; import java.net.*; import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class ResumeChecksClient extends SSLContextTemplate { enum TestMode { @@ -56,49 +59,60 @@ enum TestMode { CIPHER_SUITE, SIGNATURE_SCHEME } + static TestMode testMode; public static void main(String[] args) throws Exception { - new ResumeChecksClient(TestMode.valueOf(args[0])).run(); + testMode = TestMode.valueOf(args[0]); + new ResumeChecksClient().test(); } - private final TestMode testMode; - public ResumeChecksClient(TestMode mode) { - this.testMode = mode; - } - - private void run() throws Exception { - Server server = startServer(); - server.signal(); + private void test() throws Exception { + Server server = new Server(); SSLContext sslContext = createClientSSLContext(); - while (!server.started) { - Thread.yield(); - } - SSLSession firstSession = connect(sslContext, server.port, testMode, false); + HexFormat hex = HexFormat.of(); + long firstStartTime = System.currentTimeMillis(); + SSLSession firstSession = connect(sslContext, server.port, true); + System.err.println("firstStartTime = " + firstStartTime); + System.err.println("firstId = " + hex.formatHex(firstSession.getId())); + System.err.println("firstSession.getCreationTime() = " + + firstSession.getCreationTime()); - server.signal(); long secondStartTime = System.currentTimeMillis(); - Thread.sleep(10); - SSLSession secondSession = connect(sslContext, server.port, testMode, true); - - server.go = false; - server.signal(); + SSLSession secondSession = connect(sslContext, server.port, false); + System.err.println("secondStartTime = " + secondStartTime); + // Note: Ids will never match with TLS 1.3 due to spec + System.err.println("secondId = " + hex.formatHex(secondSession.getId())); + System.err.println("secondSession.getCreationTime() = " + + secondSession.getCreationTime()); switch (testMode) { case BASIC: // fail if session is not resumed - checkResumedSession(firstSession, secondSession); + try { + checkResumedSession(firstSession, secondSession); + } catch (Exception e) { + throw new AssertionError("secondSession did not resume: FAIL", + e); + } + System.out.println("secondSession used resumption: PASS"); break; case VERSION_2_TO_3: case VERSION_3_TO_2: case CIPHER_SUITE: case SIGNATURE_SCHEME: // fail if a new session is not created - if (secondSession.getCreationTime() <= secondStartTime) { - throw new RuntimeException("Existing session was used"); + try { + checkResumedSession(firstSession, secondSession); + System.err.println("firstSession = " + firstSession); + System.err.println("secondSession = " + secondSession); + throw new AssertionError("Second connection should not " + + "have resumed first session: FAIL"); + } catch (Exception e) { + System.out.println("secondSession didn't use resumption: PASS"); } break; default: - throw new RuntimeException("unknown mode: " + testMode); + throw new AssertionError("unknown mode: " + testMode); } } @@ -134,51 +148,29 @@ public boolean permits(Set primitives, } private static SSLSession connect(SSLContext sslContext, int port, - TestMode mode, boolean second) { + boolean first) { try { SSLSocket sock = (SSLSocket) sslContext.getSocketFactory().createSocket(); SSLParameters params = sock.getSSLParameters(); - switch (mode) { - case BASIC: - // do nothing to ensure resumption works - break; - case VERSION_2_TO_3: - if (second) { - params.setProtocols(new String[] {"TLSv1.3"}); - } else { - params.setProtocols(new String[] {"TLSv1.2"}); - } - break; - case VERSION_3_TO_2: - if (second) { - params.setProtocols(new String[] {"TLSv1.2"}); - } else { - params.setProtocols(new String[] {"TLSv1.3"}); - } - break; - case CIPHER_SUITE: - if (second) { - params.setCipherSuites( - new String[] {"TLS_AES_256_GCM_SHA384"}); - } else { - params.setCipherSuites( - new String[] {"TLS_AES_128_GCM_SHA256"}); - } - break; - case SIGNATURE_SCHEME: - AlgorithmConstraints constraints = - params.getAlgorithmConstraints(); - if (second) { - params.setAlgorithmConstraints(new NoSig("ecdsa")); - } else { - params.setAlgorithmConstraints(new NoSig("rsa")); - } - break; - default: - throw new RuntimeException("unknown mode: " + mode); + switch (testMode) { + case BASIC -> {} // do nothing + case VERSION_2_TO_3 -> params.setProtocols(new String[]{ + first ? "TLSv1.2" : "TLSv1.3"}); + case VERSION_3_TO_2 -> params.setProtocols(new String[]{ + first ? "TLSv1.3" : "TLSv1.2"}); + case CIPHER_SUITE -> params.setCipherSuites( + new String[]{ + first ? "TLS_AES_128_GCM_SHA256" : + "TLS_AES_256_GCM_SHA384"}); + case SIGNATURE_SCHEME -> + params.setAlgorithmConstraints(new NoSig( + first ? "rsa" : "ecdsa")); + default -> + throw new AssertionError("unknown mode: " + + testMode); } sock.setSSLParameters(params); sock.connect(new InetSocketAddress("localhost", port)); @@ -195,7 +187,7 @@ private static SSLSession connect(SSLContext sslContext, int port, return result; } catch (Exception ex) { // unexpected exception - throw new RuntimeException(ex); + throw new AssertionError(ex); } } @@ -274,65 +266,63 @@ private static void checkResumedSession(SSLSession initSession, } } - private static Server startServer() { - Server server = new Server(); - new Thread(server).start(); - return server; - } - - private static class Server extends SSLContextTemplate implements Runnable { - - public volatile boolean go = true; - private boolean signal = false; - public volatile int port = 0; - public volatile boolean started = false; + private static class Server extends SSLContextTemplate { + public int port; + private final SSLServerSocket ssock; + ExecutorService threadPool = Executors.newFixedThreadPool(1); + CountDownLatch serverLatch = new CountDownLatch(1); - private synchronized void waitForSignal() { - while (!signal) { - try { - wait(); - } catch (InterruptedException ex) { - // do nothing - } - } - signal = false; - } - public synchronized void signal() { - signal = true; - notify(); - } - - @Override - public void run() { + Server() { try { - SSLContext sc = createServerSSLContext(); ServerSocketFactory fac = sc.getServerSocketFactory(); - SSLServerSocket ssock = (SSLServerSocket) - fac.createServerSocket(0); - this.port = ssock.getLocalPort(); + ssock = (SSLServerSocket) fac.createServerSocket(0); + port = ssock.getLocalPort(); - waitForSignal(); - started = true; - while (go) { + // Thread to allow multiple clients to connect + new Thread(() -> { try { - System.out.println("Waiting for connection"); - Socket sock = ssock.accept(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String line = reader.readLine(); - System.out.println("server read: " + line); - PrintWriter out = new PrintWriter( - new OutputStreamWriter(sock.getOutputStream())); - out.println(line); - out.flush(); - waitForSignal(); + System.err.println("Server starting to accept"); + serverLatch.countDown(); + do { + threadPool.submit( + new ServerThread((SSLSocket) ssock.accept())); + } while (true); } catch (Exception ex) { - ex.printStackTrace(); + throw new AssertionError("Server Down", ex); + } finally { + threadPool.close(); } + }).start(); + + } catch (Exception e) { + throw new AssertionError(e); + } + } + + static class ServerThread extends Thread { + SSLSocket sock; + + ServerThread(SSLSocket s) { + this.sock = s; + System.err.println("(Server) client connection on port " + + sock.getPort()); + } + + public void run() { + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String line = reader.readLine(); + System.out.println("server read: " + line); + PrintWriter out = new PrintWriter( + new OutputStreamWriter(sock.getOutputStream())); + out.println(line); + out.flush(); + out.close(); + } catch (Exception e) { + throw new AssertionError("Server thread error", e); } - } catch (Exception ex) { - throw new RuntimeException(ex); } } } diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java index 0d5413d1fa21..fa79567f35da 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksServer.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8206929 + * @bug 8206929 8333857 * @summary ensure that server only resumes a session if certain properties * of the session are compatible with the new connection * @library /javax/net/ssl/templates @@ -48,6 +48,9 @@ import java.security.*; import java.net.*; import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class ResumeChecksServer extends SSLContextTemplate { @@ -60,51 +63,50 @@ enum TestMode { SIGNATURE_SCHEME } - public static void main(String[] args) throws Exception { - - new ResumeChecksServer(TestMode.valueOf(args[0])).run(); - } - private final TestMode testMode; + static CountDownLatch latch = new CountDownLatch(1); + static TestMode testMode; + static int serverPort; - public ResumeChecksServer(TestMode testMode) { - this.testMode = testMode; + public static void main(String[] args) throws Exception { + testMode = TestMode.valueOf(args[0]); + new ResumeChecksServer().test(); } - private void run() throws Exception { - SSLSession secondSession = null; + private void test() throws Exception { + SSLSession firstSession, secondSession; + HexFormat hex = HexFormat.of(); - SSLContext sslContext = createServerSSLContext(); - ServerSocketFactory fac = sslContext.getServerSocketFactory(); - SSLServerSocket ssock = (SSLServerSocket) - fac.createServerSocket(0); + serverPort = new Server().port; + latch.await(); + Client c = new Client(serverPort); - Client client = startClient(ssock.getLocalPort()); + System.out.println("Waiting for connection"); + long firstStartTime = System.currentTimeMillis(); + firstSession = c.test(); - try { - connect(client, ssock, testMode, false); - } catch (Exception ex) { - throw new RuntimeException(ex); - } + System.err.println("firstStartTime = " + firstStartTime); + System.err.println("firstId = " + hex.formatHex(firstSession.getId())); + System.err.println("firstSession.getCreationTime() = " + + firstSession.getCreationTime()); long secondStartTime = System.currentTimeMillis(); - Thread.sleep(10); - try { - secondSession = connect(client, ssock, testMode, true); - } catch (SSLHandshakeException ex) { - // this is expected - } catch (Exception ex) { - throw new RuntimeException(ex); - } + secondSession = c.test(); - client.go = false; - client.signal(); + System.err.println("secondStartTime = " + secondStartTime); + // Note: Ids will never match with TLS 1.3 due to spec + System.err.println("secondId = " + hex.formatHex(secondSession.getId())); + System.err.println("secondSession.getCreationTime() = " + + secondSession.getCreationTime()); switch (testMode) { case BASIC: // fail if session is not resumed - if (secondSession.getCreationTime() > secondStartTime) { - throw new RuntimeException("Session was not reused"); + if (firstSession.getCreationTime() != + secondSession.getCreationTime()) { + throw new AssertionError("Session was not reused: FAIL"); } + + System.out.println("secondSession used resumption: PASS"); break; case CLIENT_AUTH: // throws an exception if the client is not authenticated @@ -115,24 +117,23 @@ private void run() throws Exception { case CIPHER_SUITE: case SIGNATURE_SCHEME: // fail if a new session is not created - if (secondSession.getCreationTime() <= secondStartTime) { - throw new RuntimeException("Existing session was used"); + if (secondSession.getCreationTime() < secondStartTime) { + throw new AssertionError("Existing session was used: FAIL"); } + System.out.println("secondSession not resumed: PASS"); break; default: - throw new RuntimeException("unknown mode: " + testMode); + throw new AssertionError("unknown mode: " + testMode); } } private static class NoSig implements AlgorithmConstraints { - private final String alg; NoSig(String alg) { this.alg = alg; } - private boolean test(String a) { return !a.toLowerCase().contains(alg.toLowerCase()); } @@ -140,160 +141,137 @@ private boolean test(String a) { public boolean permits(Set primitives, Key key) { return true; } + public boolean permits(Set primitives, String algorithm, AlgorithmParameters parameters) { - return test(algorithm); } + public boolean permits(Set primitives, String algorithm, Key key, AlgorithmParameters parameters) { - return test(algorithm); } } - private static SSLSession connect(Client client, SSLServerSocket ssock, - TestMode mode, boolean second) throws Exception { - try { - client.signal(); - System.out.println("Waiting for connection"); - SSLSocket sock = (SSLSocket) ssock.accept(); - SSLParameters params = sock.getSSLParameters(); + private static class Client extends SSLContextTemplate { + private final int port; + private final SSLContext sc; + public SSLSession session; - switch (mode) { - case BASIC: - // do nothing to ensure resumption works - break; - case CLIENT_AUTH: - if (second) { - params.setNeedClientAuth(true); - } else { - params.setNeedClientAuth(false); - } - break; - case VERSION_2_TO_3: - if (second) { - params.setProtocols(new String[] {"TLSv1.3"}); - } else { - params.setProtocols(new String[] {"TLSv1.2"}); - } - break; - case VERSION_3_TO_2: - if (second) { - params.setProtocols(new String[] {"TLSv1.2"}); - } else { - params.setProtocols(new String[] {"TLSv1.3"}); - } - break; - case CIPHER_SUITE: - if (second) { - params.setCipherSuites( - new String[] {"TLS_AES_128_GCM_SHA256"}); - } else { - params.setCipherSuites( - new String[] {"TLS_AES_256_GCM_SHA384"}); - } - break; - case SIGNATURE_SCHEME: - params.setNeedClientAuth(true); - AlgorithmConstraints constraints = - params.getAlgorithmConstraints(); - if (second) { - params.setAlgorithmConstraints(new NoSig("ecdsa")); - } else { - params.setAlgorithmConstraints(new NoSig("rsa")); - } - break; - default: - throw new RuntimeException("unknown mode: " + mode); - } - sock.setSSLParameters(params); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String line = reader.readLine(); - System.out.println("server read: " + line); + Client(int port) throws Exception { + sc = createClientSSLContext(); + this.port = port; + } + + public SSLSession test() throws Exception { + SSLSocket sock = null; + latch.await(); + do { + try { + sock = (SSLSocket) sc.getSocketFactory().createSocket(); + } catch (IOException e) { + // If the server never starts, test will time out. + System.err.println("client trying again to connect"); + Thread.sleep(500); + } + } while (sock == null); + sock.connect(new InetSocketAddress("localhost", port)); PrintWriter out = new PrintWriter( new OutputStreamWriter(sock.getOutputStream())); - out.println(line); + out.println("message"); out.flush(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String inMsg = reader.readLine(); + System.out.println("Client received: " + inMsg); out.close(); - SSLSession result = sock.getSession(); + session = sock.getSession(); sock.close(); - return result; - } catch (SSLHandshakeException ex) { - if (!second) { - throw ex; - } + return session; } - return null; - } - - private static Client startClient(int port) { - Client client = new Client(port); - new Thread(client).start(); - return client; } - private static class Client extends SSLContextTemplate implements Runnable { - - public volatile boolean go = true; - private boolean signal = false; - private final int port; - - Client(int port) { - this.port = port; - } - - private synchronized void waitForSignal() { - while (!signal) { + // The server will only have two connections each tests + private static class Server extends SSLContextTemplate { + public int port; + ExecutorService threadPool = Executors.newFixedThreadPool(1); + // Stores the certs from the first connection in mode LOCAL_CERTS + // first connection to the server + static boolean first = true; + + Server() throws Exception { + SSLContext sc = createServerSSLContext(); + ServerSocketFactory fac = sc.getServerSocketFactory(); + SSLServerSocket ssock = (SSLServerSocket) fac.createServerSocket(0); + port = ssock.getLocalPort(); + + // Thread to allow multiple clients to connect + new Thread(() -> { try { - wait(); - } catch (InterruptedException ex) { - // do nothing + System.err.println("Server starting to accept"); + latch.countDown(); + do { + threadPool.submit(new ServerThread(ssock.accept())); + } while (true); + } catch (Exception ex) { + throw new AssertionError("Server Down", ex); + } finally { + threadPool.close(); } - } - signal = false; - - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - // do nothing - } - } - public synchronized void signal() { - signal = true; - notify(); + }).start(); } - public void run() { - try { + static class ServerThread implements Runnable { + final SSLSocket sock; - SSLContext sc = createClientSSLContext(); + ServerThread(Socket s) { + this.sock = (SSLSocket) s; + System.err.println("(Server) client connection on port " + + sock.getPort()); + } - waitForSignal(); - while (go) { - try { - SSLSocket sock = (SSLSocket) - sc.getSocketFactory().createSocket(); - sock.connect(new InetSocketAddress("localhost", port)); - PrintWriter out = new PrintWriter( - new OutputStreamWriter(sock.getOutputStream())); - out.println("message"); - out.flush(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - String inMsg = reader.readLine(); - System.out.println("Client received: " + inMsg); - out.close(); - sock.close(); - waitForSignal(); - } catch (Exception ex) { - ex.printStackTrace(); + + public void run() { + try { + SSLParameters params = sock.getSSLParameters(); + switch (testMode) { + case BASIC -> {} // do nothing + case CLIENT_AUTH -> params.setNeedClientAuth(!first); + case VERSION_2_TO_3 -> params.setProtocols(new String[]{ + first ? "TLSv1.2" : "TLSv1.3"}); + case VERSION_3_TO_2 -> params.setProtocols(new String[]{ + first ? "TLSv1.3" : "TLSv1.2"}); + case CIPHER_SUITE -> params.setCipherSuites( + new String[]{ + first ? "TLS_AES_256_GCM_SHA384" : + "TLS_AES_128_GCM_SHA256"}); + case SIGNATURE_SCHEME -> { + params.setNeedClientAuth(true); + params.setAlgorithmConstraints(new NoSig( + first ? "ecdsa_secp521r1_sha512" : + "ecdsa_secp384r1_sha384")); + } + default -> + throw new AssertionError("Server: " + + "unknown mode: " + testMode); } + sock.setSSLParameters(params); + BufferedReader reader = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + String line = reader.readLine(); + System.err.println("server read: " + line); + PrintWriter out = new PrintWriter( + new OutputStreamWriter(sock.getOutputStream())); + out.println(line); + out.flush(); + out.close(); + SSLSession session = sock.getSession(); + first = false; + System.err.println("server socket closed: " + session); + } catch (Exception e) { + throw new AssertionError("Server error", e); } - } catch (Exception ex) { - throw new RuntimeException(ex); } } } diff --git a/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java b/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java new file mode 100644 index 000000000000..16c9bd655328 --- /dev/null +++ b/test/jdk/sun/security/util/AlgorithmConstraints/InvalidCryptoDisabledAlgos.java @@ -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. + */ + +/* + * @test + * @bug 8244336 + * @modules java.base/sun.security.util + * @summary Check that invalid property values for + * "jdk.crypto.disabledAlgorithms" are rejected + * @library /test/lib + * @run main/othervm InvalidCryptoDisabledAlgos "*" + * @run main/othervm InvalidCryptoDisabledAlgos "." + * @run main/othervm InvalidCryptoDisabledAlgos ".AES" + * @run main/othervm InvalidCryptoDisabledAlgos "Cipher." + * @run main/othervm InvalidCryptoDisabledAlgos "A.B" + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,." + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,.AES" + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,Cipher." + * @run main/othervm InvalidCryptoDisabledAlgos "KeyStore.MY,A.B" + */ +import java.security.MessageDigest; +import java.security.Security; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import sun.security.util.CryptoAlgorithmConstraints; + +public class InvalidCryptoDisabledAlgos { + + public static void main(String[] args) throws Exception { + System.out.println("Invalid Property Value = " + args[0]); + Security.setProperty("jdk.crypto.disabledAlgorithms", args[0]); + // Trigger the check to parse and validate property value + Utils.runAndCheckException(() -> CryptoAlgorithmConstraints.permits( + "x", "y"), + t -> Asserts.assertTrue( + t instanceof ExceptionInInitializerError && + t.getCause() instanceof IllegalArgumentException)); + } +} diff --git a/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java b/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java index 1076aafb6b0c..84b8dead4250 100644 --- a/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java +++ b/test/jdk/sun/security/x509/URICertStore/CRLReadTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, 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 @@ -22,45 +22,101 @@ */ /* - * @test + * @test id=0 * @bug 8191808 8179502 * @summary check that CRL download is interrupted if it takes too long * @modules java.base/sun.security.x509 * java.base/sun.security.util * @library /test/lib - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1 + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1 * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1s + */ + +/* + * @test id=1 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1s * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=4 + */ + +/* + * @test id=2 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=200 * CRLReadTimeout 1000 true - * @run main/othervm -Dcom.sun.security.crl.readtimeout=1500ms + */ + +/* + * @test id=3 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=1500ms * CRLReadTimeout 5000 false - * @run main/othervm -Dcom.sun.security.crl.readtimeout=4500ms - * CRLReadTimeout 1000 true */ -import java.io.*; +/* + * @test id=4 + * @bug 8191808 8179502 + * @summary check that CRL download is interrupted if it takes too long + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm -Djava.security.debug=certpath -Dcom.sun.security.crl.readtimeout=4500ms + * CRLReadTimeout 100 true + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.math.BigInteger; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; -import java.security.cert.*; +import java.security.cert.CRLException; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertificateFactory; +import java.security.cert.PKIXParameters; +import java.security.cert.PKIXRevocationChecker; +import java.security.cert.TrustAnchor; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; -import static java.security.cert.PKIXRevocationChecker.Option.*; +import static java.security.cert.PKIXRevocationChecker.Option.NO_FALLBACK; +import static java.security.cert.PKIXRevocationChecker.Option.PREFER_CRLS; +import static java.security.cert.PKIXRevocationChecker.Option.SOFT_FAIL; import com.sun.net.httpserver.HttpServer; import jdk.test.lib.SecurityTools; import jdk.test.lib.process.OutputAnalyzer; import sun.security.util.SignatureUtil; -import sun.security.x509.*; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.CRLExtensions; +import sun.security.x509.CRLNumberExtension; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.X500Name; +import sun.security.x509.X509CRLImpl; public class CRLReadTimeout { @@ -117,9 +173,10 @@ private static void testTimeout(int port, boolean expectedPass) // unwrap soft fail exceptions and check for SocketTimeoutException List softExc = prc.getSoftFailExceptions(); if (expectedPass) { - if (softExc.size() > 0) { + if (!softExc.isEmpty()) { throw new RuntimeException("Expected to pass, found " + - softExc.size() + " soft fail exceptions"); + softExc.size() + + " soft fail exceptions"); } } else { boolean foundSockTOExc = false; @@ -182,7 +239,7 @@ public CrlHttpServer(int timeout) throws IOException { } public void start() throws IOException { - server.bind(new InetSocketAddress(0), 0); + server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); server.createContext("/crl", t -> { try (InputStream is = t.getRequestBody()) { is.readAllBytes(); diff --git a/test/jdk/tools/jar/ReproducibleJar.java b/test/jdk/tools/jar/ReproducibleJar.java index ed5e2ed2ae34..5f59d1cbe414 100644 --- a/test/jdk/tools/jar/ReproducibleJar.java +++ b/test/jdk/tools/jar/ReproducibleJar.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 @@ -66,7 +66,9 @@ public class ReproducibleJar { private static final TimeZone TZ = TimeZone.getDefault(); private static final boolean DST = TZ.inDaylightTime(new Date()); private static final String UNIX_2038_ROLLOVER_TIME = "2038-01-19T03:14:07Z"; + private static final String UNIX_EPOCH_TIME = "1970-01-01T00:00:00Z"; private static final Instant UNIX_2038_ROLLOVER = Instant.parse(UNIX_2038_ROLLOVER_TIME); + private static final Instant UNIX_EPOCH = Instant.parse(UNIX_EPOCH_TIME); private static final File DIR_OUTER = new File("outer"); private static final File DIR_INNER = new File(DIR_OUTER, "inner"); private static final File FILE_INNER = new File(DIR_INNER, "foo.txt"); @@ -231,12 +233,15 @@ static void checkFileTime(long now, long original) { if (Math.abs(now - original) > PRECISION) { // If original time is after UNIX 2038 32bit rollover - // and the now time is exactly the rollover time, then assume + // and the now time is exactly the rollover time or UNIX epoch time, then assume // running on a file system that only supports to 2038 (e.g.XFS) and pass test - if (FileTime.fromMillis(original).toInstant().isAfter(UNIX_2038_ROLLOVER) && - FileTime.fromMillis(now).toInstant().equals(UNIX_2038_ROLLOVER)) { - System.out.println("Checking file time after Unix 2038 rollover," + - " and extracted file time is " + UNIX_2038_ROLLOVER_TIME + ", " + + Instant originalInstant = FileTime.fromMillis(original).toInstant(); + Instant nowInstant = FileTime.fromMillis(now).toInstant(); + if (originalInstant.isAfter(UNIX_2038_ROLLOVER) && + (nowInstant.equals(UNIX_2038_ROLLOVER) || + nowInstant.equals(UNIX_EPOCH))) { + System.out.println("Checking file time after Unix 2038 rollover," + + " and extracted file time is " + nowInstant + ", " + " Assuming restricted file system, pass file time check."); } else { throw new AssertionError("checkFileTime failed," + diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index da884dee1706..11daad5244f3 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc groups=TEST.groups # Minimum jtreg version -requiredVersion=7.3.1+1 +requiredVersion=7.4+1 # Use new module options useNewOptions=true diff --git a/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java b/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java index 6f1c86b950c1..2e9b04a634b2 100644 --- a/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.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 @@ -46,7 +46,11 @@ public void hangListenTimeoutTest() { System.err.printf("Unexpected return value: %s\n", HangingRemoteAgent.state(false, null).eval("33;")); } catch (IllegalStateException ex) { - assertTrue(ex.getMessage().startsWith(EXPECTED_ERROR), ex.getMessage()); + if (!ex.getMessage().startsWith(EXPECTED_ERROR)) { + // unexpected message in the exception, rethrow the original exception + throw ex; + } + // received expected exception return; } fail("Expected IllegalStateException"); diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT index 9b91a0dfcc15..27576a2d0401 100644 --- a/test/lib-test/TEST.ROOT +++ b/test/lib-test/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ keys=randomness # Minimum jtreg version -requiredVersion=7.3.1+1 +requiredVersion=7.4+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/lib-test/jdk/test/whitebox/WaitForRefProcTest.java b/test/lib-test/jdk/test/whitebox/WaitForRefProcTest.java new file mode 100644 index 000000000000..1a254775f771 --- /dev/null +++ b/test/lib-test/jdk/test/whitebox/WaitForRefProcTest.java @@ -0,0 +1,30 @@ +/* + * @test + * @summary Test WhiteBox.waitForReferenceProcessing + * @bug 8305186 8355632 + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @modules java.base/java.lang.ref:open + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -ea -esa + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * WaitForRefProcTest + */ + +import jdk.test.whitebox.WhiteBox; + +public class WaitForRefProcTest { + + public static void main(String[] args) { + WhiteBox.getWhiteBox().fullGC(); + try { + boolean ret = WhiteBox.getWhiteBox().waitForReferenceProcessing(); + System.out.println("wFRP returned " + ret); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("test caught InterruptedException"); + } + } +} diff --git a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java index fc3b793c47a0..13d2fb86cfa4 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java @@ -31,6 +31,7 @@ // in test environment. public class DockerRunOptions { public String imageNameAndTag; + public ArrayList engineOpts = new ArrayList<>(); public ArrayList dockerOpts = new ArrayList<>(); public String command; // normally a full path to java public ArrayList javaOpts = new ArrayList<>(); @@ -70,6 +71,11 @@ public DockerRunOptions addDockerOpts(String... opts) { return this; } + public final DockerRunOptions addEngineOpts(String... opts) { + Collections.addAll(engineOpts, opts); + return this; + } + public DockerRunOptions addJavaOpts(String... opts) { Collections.addAll(javaOpts, opts); return this; diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 4a8915d46310..3d721b598b93 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -83,6 +83,14 @@ public static boolean isDockerEngineAvailable() throws Exception { return isDockerEngineAvailable; } + /** + * Checks if the actual engine command is podman. + * + * @return {@code true} if engine is podman. {@code false} otherwise. + */ + public static boolean isPodman() { + return Container.ENGINE_COMMAND.contains("podman"); + } /** * Convenience method, will check if docker engine is available and usable; @@ -121,6 +129,26 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { return true; } + private static String getEngineInfo(String format) throws Exception { + return execute(Container.ENGINE_COMMAND, "info", "-f", format).getStdout(); + } + + /** + * Determine if the engine is running in root-less mode. + * + * @return {@code true} when running root-less (podman or docker). {@code false} + * otherwise. + * + * @throws Exception + */ + public 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")); + } + /** * Build a container image that contains JDK under test. * The jdk will be placed under the "/jdk/" folder inside the image/container file system. @@ -202,6 +230,9 @@ private static void buildImage(String imageName, Path buildDir) throws Exception */ public static List buildJavaCommand(DockerRunOptions opts) throws Exception { List cmd = buildContainerCommand(); + if (!opts.engineOpts.isEmpty()) { + cmd.addAll(opts.engineOpts); + } cmd.add("run"); if (opts.tty) cmd.add("--tty=true"); diff --git a/test/lib/jdk/test/lib/process/OutputAnalyzer.java b/test/lib/jdk/test/lib/process/OutputAnalyzer.java index 4b4e97274770..24bb18e3d4b7 100644 --- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java +++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java @@ -224,6 +224,20 @@ public boolean stdoutContains(String expectedString) { return getStdout().contains(expectedString); } + /** + * Returns true if stderr contains the given string + */ + public boolean stderrContains(String expectedString) { + return getStderr().contains(expectedString); + } + + /** + * Returns true if either stdout or stderr contains the given string + */ + public boolean contains(String expectedString) { + return stdoutContains(expectedString) || stderrContains(expectedString); + } + /** * Verify that the stdout and stderr contents of output buffer contains the string * diff --git a/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java b/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java index f0356fbe485f..88508f89587f 100644 --- a/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java +++ b/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java @@ -32,7 +32,7 @@ public class OpensslArtifactFetcher { - private static final String OPENSSL_BUNDLE_VERSION = "3.0.14"; + private static final String OPENSSL_BUNDLE_VERSION = "3.5.1"; private static final String OPENSSL_ORG = "jpg.tests.jdk.openssl"; /** diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 8586434c8ea6..94e18137680a 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -539,7 +539,7 @@ private static Method getWaitForReferenceProcessingMethod() { try { wfrp = Reference.class.getDeclaredMethod("waitForReferenceProcessing"); wfrp.setAccessible(true); - assert wfrp.getReturnType() == Boolean.class; + assert wfrp.getReturnType().equals(boolean.class); Class[] ev = wfrp.getExceptionTypes(); assert ev.length == 1; assert ev[0] == InterruptedException.class; diff --git a/test/micro/org/openjdk/bench/java/lang/reflect/NativeMethodInvoke.java b/test/micro/org/openjdk/bench/java/lang/reflect/NativeMethodInvoke.java new file mode 100644 index 000000000000..b48cef580374 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/reflect/NativeMethodInvoke.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.reflect; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark for regression in native method invocation. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) +@Fork(3) +public class NativeMethodInvoke { + + private Method objectHashCode; + private Method threadCurrentThread; + + private Object[] objects; + + @Setup + public void setup() throws ReflectiveOperationException { + objects = new Object[]{ + 1, 5L, + 5.6d, 23.11f, + Boolean.TRUE, 'd' + }; + + objectHashCode = Object.class.getDeclaredMethod("hashCode"); + threadCurrentThread = Thread.class.getDeclaredMethod("currentThread"); + } + + @Benchmark + public void objectHashCode(Blackhole bh) throws ReflectiveOperationException { + for (var obj : objects) { + bh.consume(objectHashCode.invoke(obj)); + } + } + + @Benchmark + public Object threadCurrentThread() throws ReflectiveOperationException { + return threadCurrentThread.invoke(null); + } +}