diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..ee91f5d33e2 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,184 @@ +# git blame ignore revs file +# +# The list of revisions below will be ignored by git-blame (1) if this file gets +# passed via the --ignore-revs-file command line option or is configured using +# the blame.ignoreRevsFile key. +# +# Only add commits that obviously do not change semantics, e.g. mechanical refactorings +# or formatting. Always add the commit message as a comment above the revision +# to keep the file readable. + +# 8299973: Replace NULL with nullptr in share/utilities/ +1084fd24eb118d4131538c2a3ead714db7d0357b + +# 8299974: Replace NULL with nullptr in share/adlc/ +62537d200f01d58ff1c236f31f71c5839316db9e + +# 8300081: Replace NULL with nullptr in share/asm/ +9d5bab11f08a992803399f422d75b17f8607df72 + +# 8300086: Replace NULL with nullptr in share/c1/ +90d5041b6a055d6266140ffea2aa9a3b08b32209 + +# 8300087: Replace NULL with nullptr in share/cds/ +eca64795be63c599a637ce2a7f740b2d0a1ec9bc + +# 8300222: Replace NULL with nullptr in share/logging +bd5ca953058704087da4bc5796b3ce28ce2a8f78 + +# 8300240: Replace NULL with nullptr in share/ci/ +f52d35c84b7333809156d201c866793854143888 + +# 8300241: Replace NULL with nullptr in share/classfile/ +49ff52087be8b95cbf369518281312ecc9d83618 + +# 8300242: Replace NULL with nullptr in share/code/ +cfe57466ddecb93b528478d0b053b089dd1ed285 + +# 8300243: Replace NULL with nullptr in share/compiler/ +fcbf9d052efd16821750fb20813f8030ee828472 + +# 8300244: Replace NULL with nullptr in share/interpreter/ +a5d8e12872d9de399fa97b33896635d101b71372 + +# 8300245: Replace NULL with nullptr in share/jfr/ +cc396895e5a1dac49f4e341ce91c04b8c092d0af + +# 8300651: Replace NULL with nullptr in share/runtime/ +71107f4648d8f31a7bcc0aa5202ef46230df583f + +# 8301068: Replace NULL with nullptr in share/jvmci/ +90ec19efeda90f13a918b4481fe6ee552ab2af66 + +# 8301069: Replace NULL with nullptr in share/libadt/ +b0376a5f4421fb58c0feeddfce2c2083314e400c + +# 8301070: Replace NULL with nullptr in share/memory/ +d98a323a8b972c17a066c597a81b164681ad5589 + +# 8301072: Replace NULL with nullptr in share/oops/ +c8ace482edead720c865cf996729a316025d937e + +# 8301074: Replace NULL with nullptr in share/opto/ +5726d31e56530bbe7dee61ae04b126e20cb3611d + +# 8301076: Replace NULL with nullptr in share/prims/ +b76a52f2104b63e84e5d09f47ce01dd0cb3935d7 + +# 8301077: Replace NULL with nullptr in share/services/ +5c1ec82656323872c4628026662fe5b62e7a61e3 + +# 8301178: Replace NULL with nullptr in share/gc/epsilon/ +b77abc6a0daed0e01a9003d42493320376dc98bc + +# 8301179: Replace NULL with nullptr in share/gc/serial/ +107e184d59c0bbed6441a3c1a9bfd4527da3bce5 + +# 8301180: Replace NULL with nullptr in share/gc/parallel/ +3758487fda61b27e7e684413793ed28c0b9e64d3 + +# 8301223: Replace NULL with nullptr in share/gc/g1/ +75a4edca6b9fa6b3e66b564aeb4d7ca8acf02491 + +# 8301225: Replace NULL with nullptr in share/gc/shenandoah/ +0c9658446d111ec944f06b7a8a4e3ae7bf53ee8d + +# 8301477: Replace NULL with nullptr in os/aix +43288bbd684abfcefdf385ed1e0307070399ccbf + +# 8301478: Replace NULL with nullptr in os/bsd +716f1df609e7f0aa7b3b9383d23dde5c71017d02 + +# 8301479: Replace NULL with nullptr in os/linux +ac9e046748a9bb6ee065dc473d82135ce36043b7 + +# 8301480: Replace NULL with nullptr in os/posix +4539899c55c77771b951d005c17550ef9ac94819 + +# 8301481: Replace NULL with nullptr in os/windows +c91cd2814baa8dee2af8af0fecf9185d4a0a44cf + +# 8301493: Replace NULL with nullptr in cpu/aarch64 +948f3b3c24709eca3aa6c3f0db6adb9226d6f9ac + +# 8301494: Replace NULL with nullptr in cpu/arm +c4ffe4bf6369d5b271aa8689b8648f3fe8dcabed + +# 8301495: Replace NULL with nullptr in cpu/ppc +0826ceee65ab83f643a77716f8f12d0060369923 + +# 8301496: Replace NULL with nullptr in cpu/riscv +d2ce04bb101002abfdb7c8adb3fa8ea267903c36 + +# 8301497: Replace NULL with nullptr in cpu/s390 +54f7b6ca34986cc26c5b91c6724b9a1754c94391 + +# 8301498: Replace NULL with nullptr in cpu/x86 +4154a980ca28c1ae56db26e3dce64c07c225de12 + +# 8301499: Replace NULL with nullptr in cpu/zero +4e327db1d127c652ef39e31c164e36ae429a0065 + +# 8301500: Replace NULL with nullptr in os_cpu/aix_ppc +c8307e37fdf4453cade84efc113d93dd14333fd0 + +# 8301501: Replace NULL with nullptr in os_cpu/bsd_aarch64 +218223e4a31d485935655cb3f186a752defd8fa8 + +# 8301502: Replace NULL with nullptr in os_cpu/bsd_x86 +6daff6b26946748360d59a12e9069a08ab5ca06d + +# 8301503: Replace NULL with nullptr in os_cpu/bsd_zero +8cc399b672c6ce08037685b3a3a2db3c53a87b50 + +# 8301504: Replace NULL with nullptr in os_cpu/linux_aarch64 +13fcd602d37eb0095f169255128588b872639571 + +# 8301505: Replace NULL with nullptr in os_cpu/linux_arm +b81f0ff43ac8d1431f2f5dccb7499a3a1503823d + +# 8301506: Replace NULL with nullptr in os_cpu/linux_ppc +b1e96989b693aadea082a01576e25f85ed28ff0d + +# 8301507: Replace NULL with nullptr in os_cpu/linux_riscv +182d1b2fb7034b6e9177dc360cbea43d548c3ff0 + +# 8301508: Replace NULL with nullptr in os_cpu/linux_s390 +d097b5e6285e1a59632211e006592fedf2047c09 + +# 8301509: Replace NULL with nullptr in os_cpu/linux_x86 +5d1f71daf06870810c9ca24e911d6191cc4f3006 + +# 8301511: Replace NULL with nullptr in os_cpu/linux_zero +42a286a15862d9a05ea3477a9eeab46e7b33e599 + +# 8301512: Replace NULL with nullptr in os_cpu/windows_aarch64 +ad79e49141f063a61090eda69d96dc580db88949 + +# 8301513: Replace NULL with nullptr in os_cpu/windows_x86 +c109dae48c61c6fbeacadf59d509d37d2c4d2bb8 + +# 8308092: Replace NULL with nullptr in gc/x +599fa774b875da971d66f79e5e43ede2b5ce18aa + +# 8309044: Replace NULL with nullptr, final sweep of hotspot code +4f16161607edbf69f423ced1d3c24f7af058d46b + +# 8324286: Fix backsliding on use of nullptr instead of NULL +bcb340da091e3287da8d2ecfcd017ebcc6613cae + +# 8324678: Replace NULL with nullptr in HotSpot gtests +c1281e6b45ed167df69d29a6039d81854c145ae6 + +# 8324679: Replace NULL with nullptr in HotSpot .ad files +b3ecd55601d483359819d02e70789bbd412b13da + +# 8324680: Replace NULL with nullptr in JVMTI generated code +267780bf0adf4bfd831fbc04347e297fa8f3bb01 + +# 8324681: Replace NULL with nullptr in HotSpot jtreg test native code files +a6bdee48f39993128d8095d40ab417f0102af0f4 + +# 8324799: Use correct extension for C++ test headers +998d0baab0fd051c38d9fd6021628eb863b80554 + diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 4c1d2835054..20315cda97d 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1192,8 +1192,8 @@ var getJibProfilesDependencies = function (input, common) { server: "jpg", product: "jcov", version: "3.0", - build_number: "5", - file: "bundles/jcov-3.0+5.zip", + build_number: "6", + file: "bundles/jcov-3.0+6.zip", environment_name: "JCOV_HOME", }, diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index b3fd640c292..83cfa86cf70 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -33,7 +33,7 @@ DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2027-03-27 +DEFAULT_VERSION_DATE=2027-03-23 DEFAULT_VERSION_CLASSFILE_MAJOR=72 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff --git a/make/devkit/Sysroot.gmk b/make/devkit/Sysroot.gmk index fd3d8c1b891..13395172074 100644 --- a/make/devkit/Sysroot.gmk +++ b/make/devkit/Sysroot.gmk @@ -109,7 +109,7 @@ endif EMPTY := SPACE := $(EMPTY) $(EMPTY) COMMA := , -DNF_ARCHS := $(subst $(SPACE),$(COMMA),$(RPM_ARCHS)) +DNF_ARCHS := $(foreach arch,$(RPM_ARCHS),--arch $(arch)) # Specify a dummy installation root, otherwise dnf will run into # problems trying to reconcile with the local/system state @@ -123,7 +123,7 @@ DNF_DOWNLOAD_FLAGS := \ --disablerepo='*' \ $(DNF_REPOS) \ --resolve \ - --archlist $(DNF_ARCHS) \ + $(DNF_ARCHS) \ --forcearch $(RPM_ARCH) \ --installroot $(DNF_DUMMY_INSTALL_ROOT) \ --releasever $(BASE_OS_VERSION) \ diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 7360ed604f1..ea1768c6afd 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -3475,30 +3475,34 @@ frame %{ // 4 what apparently works and saves us some spills. return_addr(STACK 4); - // Location of native (C/C++) and interpreter return values. This - // is specified to be the same as Java. In the 32-bit VM, long - // values are actually returned from native calls in O0:O1 and - // returned to the interpreter in I0:I1. The copying to and from - // the register pairs is done by the appropriate call and epilog - // opcodes. This simplifies the register allocator. - c_return_value %{ - assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || - (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), - "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; - return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); - %} - // Location of compiled Java return values. Same as C return_value %{ assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; + // enum names from opcodes.hpp + static int typeToRegLo[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + R3_num, // Op_RegN + R3_num, // Op_RegI + R3_num, // Op_RegP + F1_num, // Op_RegF + F1_num, // Op_RegD + R3_num, // Op_RegL + }; + + static int typeToRegHi[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + OptoReg::Bad, // Op_RegN + OptoReg::Bad, // Op_RegI + R3_H_num, // Op_RegP + OptoReg::Bad, // Op_RegF + F1_H_num, // Op_RegD + R3_H_num // Op_RegL + }; + return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); %} %} diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index b64943fc4de..afd9c126a21 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4904,6 +4904,11 @@ void StubGenerator::generate_compiler_stubs() { StubRoutines::_intpoly_assign = generate_intpoly_assign(); } + if (UseIntPoly25519Intrinsics) { + StubRoutines::_intpoly_mult_25519 = generate_intpoly_mult_25519(); + StubRoutines::_intpoly_square_25519 = generate_intpoly_square_25519(); + } + if (UseMD5Intrinsics) { StubRoutines::_md5_implCompress = generate_md5_implCompress(StubId::stubgen_md5_implCompress_id); StubRoutines::_md5_implCompressMB = generate_md5_implCompress(StubId::stubgen_md5_implCompressMB_id); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 360b0329d95..6e3da334f11 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -496,6 +496,9 @@ class StubGenerator: public StubCodeGenerator { address generate_intpoly_montgomeryMult_P256(); address generate_intpoly_assign(); + address generate_intpoly_mult_25519(); + address generate_intpoly_square_25519(); + // SHA3 stubs void generate_sha3_stubs(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp new file mode 100644 index 00000000000..c7395220d49 --- /dev/null +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly25519.cpp @@ -0,0 +1,306 @@ +/* + * 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. 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. + */ + +#include "macroAssembler_x86.hpp" +#include "stubGenerator_x86_64.hpp" + +#define __ _masm-> + +const int32_t term = 19; +const int32_t limbs = 5; +const int32_t bpl = 51; +const int32_t rem = 64 - bpl; +const uint64_t MASK = 0x7FFFFFFFFFFFF; +const uint64_t CARRY_ADD = 0x4000000000000; + +// Multiplication operation for polynomial arithmetic in Curve25519. +// +// This is the same algorithm as used in Java, except we use pseudo-Mersenne +// reduction to reduce register pressure instead of using the full 10 columns +// in Java. +void multiply_25519_scalar(const Register aLimbs, const Register bLimbs, const Register rLimbs, Register c[], Register bArg, Register d, Register b, Register mask, MacroAssembler* _masm) { + + for (int i = 0; i < limbs; i++) { + __ xorq(c[i], c[i]); + } + __ mov64(mask, MASK); + __ movq(bArg, bLimbs); + + // Perform high/low multiplication with signed 5x51 bit limbs + for (int i = 0; i < limbs; i++) { + __ movq(b, Address(bArg, i * 8)); + for (int j = 0; j < limbs; j++) { + __ movq(rax, Address(aLimbs, j * 8)); + __ imulq(b); // rdx:rax = a * b + __ movq(d, rax); + __ andq(d, mask); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); + // Fold in pseudo-Mersenne reduction + if ((i + j + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((i + j) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i + j) % limbs], d); + __ addq(c[(i + j + 1) % limbs], rax); + } + } + + // Carry-add with reduction from high limb + Register carry = bArg; + __ mov64(mask, CARRY_ADD); + __ movq(carry, mask); + + // Limb 3 + __ addq(carry, c[3]); + __ sarq(carry, bpl); + __ addq(c[4], carry); + __ shlq(carry, bpl); + __ subq(c[3], carry); + + // Limb 4 + __ movq(carry, mask); + __ addq(carry, c[4]); + __ sarq(carry, bpl); + + // Reduce high order limb and fold back into low order limb + __ mov64(rax, term); + __ imulq(carry); + __ addq(c[0], rax); + + __ shlq(carry, bpl); + __ subq(c[4], carry); + + // Limbs 0 - 3 + for (int i = 0; i < (limbs - 1); i++) { + __ movq(carry, mask); + __ addq(carry, c[i]); + __ sarq(carry, bpl); + __ addq(c[i + 1], carry); + __ shlq(carry, bpl); + __ subq(c[i], carry); + } + + __ pop_ppx(rdx); + + for (int i = 0; i < limbs; i++) { + __ movq(Address(rLimbs, i * 8), c[i]); + } +} + +// Squaring operation for polynomial arithmetic in Curve25519. +// +// This is the same algorithm as used in Java, except we use pseudo-Mersenne +// reduction to reduce register pressure instead of using the full 10 columns +// in Java. +void square_25519_scalar(const Register aLimbs, const Register rLimbs, Register c[], Register aArg, Register d, Register carry, Register mask, MacroAssembler* _masm) { + + for (int i = 0; i < limbs; i++) { + __ xorq(c[i], c[i]); + } + __ mov64(mask, MASK); + + // Perform high/low multiplication with signed 5x51 bit limbs + for (int i = 0; i < limbs; i++) { + __ movq(aArg, Address(aLimbs, i * 8)); + __ movq(rax, aArg); + __ imulq(aArg); // rdx:rax = a[j] * a[i] + __ movq(d, rax); + __ andq(d, mask); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); // rax = dd + if ((i * 2 + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((i * 2) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i * 2) % limbs], d); + __ addq(c[(i * 2 + 1) % limbs], rax); + for (int j = i + 1; j < limbs; j++) { + __ movq(rax, Address(aLimbs, j * 8)); + __ imulq(aArg); // rdx:rax = a * a + __ movq(d, rax); + __ andq(d, mask); + __ shlq(d, 1); + __ shrq(rax, bpl); + __ shlq(rdx, rem); + __ orq(rax, rdx); // rax = dd + __ shlq(rax, 1); + if ((j + i + 1) >= limbs) { + __ imulq(rax, rax, term); + } + if ((j + i) >= limbs) { + __ imulq(d, d, term); + } + __ addq(c[(i + j) % limbs], d); + __ addq(c[(i + j + 1) % limbs], rax); + } + } + + // Carry-add with reduction from high limb + // Limb 3 + __ mov64(mask, CARRY_ADD); + __ movq(carry, mask); + __ addq(carry, c[3]); + __ sarq(carry, bpl); + __ addq(c[4], carry); + __ shlq(carry, bpl); + __ subq(c[3], carry); + + // Limb 4 + __ movq(carry, mask); + __ addq(carry, c[4]); + __ sarq(carry, bpl); + + // Reduce high order limb and fold back into low order limb + __ mov64(rax, term); + __ imulq(carry); + __ addq(c[0], rax); + + __ shlq(carry, bpl); + __ subq(c[4], carry); + + // Limbs 0 - 3 + for (int i = 0; i < (limbs - 1); i++) { + __ movq(carry, mask); + __ addq(carry, c[i]); + __ sarq(carry, bpl); + __ addq(c[i + 1], carry); + __ shlq(carry, bpl); + __ subq(c[i], carry); + } + + __ pop_ppx(rdx); + + for (int i = 0; i < limbs; i++) { + __ movq(Address(rLimbs, i * 8), c[i]); + } +} + +address StubGenerator::generate_intpoly_mult_25519() { + StubId stub_id = StubId::stubgen_intpoly_mult_25519_id; + int entry_count = StubInfo::entry_count(stub_id); + assert(entry_count == 1, "sanity check"); + address start = load_archive_data(stub_id); + if (start != nullptr) { + return start; + } + __ align(CodeEntryAlignment); + StubCodeMark mark(this, stub_id); + start = __ pc(); + __ enter(); + + // Register Map + const Register aLimbs = c_rarg0; // rdi | rcx + const Register bLimbs = c_rarg1; // rsi | rdx + const Register rLimbs = c_rarg2; // rdx | r8 + + Register c[] = {r9, r10, r11, r12, r13}; + Register bArg = r14; + Register d = r15; + Register b = rbp; + Register mask = rbx; + + __ push_ppx(rbp); + __ push_ppx(rbx); + __ push_ppx(r12); + __ push_ppx(r13); + __ push_ppx(r14); + __ push_ppx(r15); + __ push_ppx(rdx); + + multiply_25519_scalar(aLimbs, bLimbs, rLimbs, c, bArg, d, b, mask, _masm); + + // __ pop_ppx(rdx); // restored in the helper already + __ pop_ppx(r15); + __ pop_ppx(r14); + __ pop_ppx(r13); + __ pop_ppx(r12); + __ pop_ppx(rbx); + __ pop_ppx(rbp); + + __ leave(); + __ ret(0); + + // Record the stub entry and end + store_archive_data(stub_id, start, __ pc()); + + return start; +} + +address StubGenerator::generate_intpoly_square_25519() { + StubId stub_id = StubId::stubgen_intpoly_square_25519_id; + int entry_count = StubInfo::entry_count(stub_id); + assert(entry_count == 1, "sanity check"); + address start = load_archive_data(stub_id); + if (start != nullptr) { + return start; + } + __ align(CodeEntryAlignment); + StubCodeMark mark(this, stub_id); + start = __ pc(); + __ enter(); + + // Register Map + const Register aLimbs = c_rarg0; // rdi | rcx + const Register rLimbs = c_rarg1; // rsi | rdx + Register c[] = {r9, r10, r11, r12, r13}; + Register aArg = r14; + Register d = r15; + Register carry = rbp; + Register mask = rbx; + + __ push_ppx(rbp); + __ push_ppx(rbx); + __ push_ppx(r12); + __ push_ppx(r13); + __ push_ppx(r14); + __ push_ppx(r15); + __ push_ppx(rdx); + + square_25519_scalar(aLimbs, rLimbs, c, aArg, d, carry, mask, _masm); + + // __ pop_ppx(rdx); // restored in the helper already + __ pop_ppx(r15); + __ pop_ppx(r14); + __ pop_ppx(r13); + __ pop_ppx(r12); + __ pop_ppx(rbx); + __ pop_ppx(rbp); + + __ leave(); + __ ret(0); + + // Record the stub entry and end + store_archive_data(stub_id, start, __ pc()); + + return start; +} +#undef __ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp index 308a8042993..76b6fa97fa5 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Intel Corporation. All rights reserved. + * Copyright (c) 2024, 2026, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -676,7 +676,7 @@ address StubGenerator::generate_intpoly_assign() { // KNOWN Lengths: // MontgomeryIntPolynP256: 5 = 4 + 1 // IntegerPolynomial1305: 5 = 4 + 1 - // IntegerPolynomial25519: 10 = 8 + 2 + // IntegerPolynomial25519: 5 = 4 + 1 // IntegerPolynomialP256: 10 = 8 + 2 // Curve25519OrderField: 10 = 8 + 2 // Curve25519OrderField: 10 = 8 + 2 diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4cdcb1770bb..2ca1c172542 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1407,6 +1407,10 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseIntPolyIntrinsics, false); } + if (FLAG_IS_DEFAULT(UseIntPoly25519Intrinsics)) { + UseIntPoly25519Intrinsics = true; + } + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ba48f2b4efc..ad1f384fa32 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2183,6 +2183,10 @@ void os::print_os_info(outputStream* st) { st->cr(); } + if (os::Linux::print_numa_info(st)) { + st->cr(); + } + VM_Version::print_platform_virtualization_info(st); os::Linux::print_steal_info(st); @@ -2622,6 +2626,97 @@ bool os::Linux::print_container_info(outputStream* st) { return true; } +#define SYS_DEVICES_NODE "/sys/devices/system/node" + +static size_t read_sysfs_file(const char* path, char* buf, size_t sz) { + FILE* f = os::fopen(path, "r"); + if (f == nullptr) return 0; + size_t n = fread(buf, 1, sz - 1, f); + fclose(f); + buf[n] = '\0'; + while (n > 0 && (buf[n-1] == '\n' || buf[n-1] == '\r')) buf[--n] = '\0'; + return n; +} + +static void print_numa_memory_info(outputStream* st, int node) { + char path[256]; + char line[256]; + long long mem_total = -1; + long long mem_free = -1; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/meminfo", node); + FILE* f = os::fopen(path, "r"); + if (f == nullptr) { + return; + } + + while (fgets(line, sizeof(line), f) != nullptr) { + long long mval; + if (sscanf(line, "Node %*d MemTotal: %lld kB", &mval) == 1) mem_total = mval; + if (sscanf(line, "Node %*d MemFree: %lld kB", &mval) == 1) mem_free = mval; + } + fclose(f); + + if (mem_total >= 0) { st->print_cr("mem size: %lld kB", mem_total); } + if (mem_free >= 0) { st->print_cr("mem free: %lld kB", mem_free); } +} + +static void print_numa_cpu_list(outputStream* st, int node) { + char path[256]; + char buf[1024]; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/cpulist", node); + if (read_sysfs_file(path, buf, sizeof(buf)) > 0) { + st->print_cr("cpus: %s", buf); + } else { + st->print_cr("cpus: (unavailable)"); + } +} + +bool os::Linux::print_numa_info(outputStream* st) { + if (!UseNUMA) { + // If NUMA optimizations are not enabled we don't print anything + return false; + } + + char buf[1024]; + if (read_sysfs_file("/sys/devices/system/node/online", buf, sizeof(buf)) > 0) { + st->print_cr("NUMA nodes online: %s", buf); + } else { + return false; + } + + bool first = true; + int node_count = 0; + + if (nindex_to_node() == nullptr) { + return false; + } + + for (int node: *nindex_to_node()) { + char nodepath[256]; + os::snprintf_checked(nodepath, sizeof(nodepath), SYS_DEVICES_NODE "/node%d", node); + DIR* currd = os::opendir(nodepath); + if (currd == nullptr) continue; + if (first) { + st->cr(); + first = false; + } + os::closedir(currd); + + st->print_cr("NUMA node %d", node); + StreamIndentor si(st); + print_numa_cpu_list(st, node); + print_numa_memory_info(st, node); + node_count++; + } + + if (node_count == 0) { + return false; + } + + st->print_cr("Total NUMA node count: %d", node_count); + return true; +} + void os::Linux::print_steal_info(outputStream* st) { if (has_initial_tick_info) { CPUPerfTicks pticks; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 41b5afbf5c3..51a10be1e5d 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -77,6 +77,7 @@ class os::Linux { static void print_proc_sys_info(outputStream* st); static bool print_ld_preload_file(outputStream* st); static void print_uptime_info(outputStream* st); + static bool print_numa_info(outputStream* st); public: struct CPUPerfTicks { diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 9137723fa58..d00babef40f 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -243,6 +243,16 @@ static LPVOID virtualAllocExNuma(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSiz return result; } +void* os::win32::lookup_kernelbase_symbol(const char* name) { + // Pass a small ebuf so dll_load logs failures, but don't use it here to avoid redundancy. + char ebuf[1024]; + static void* const handle = os::dll_load("KernelBase", ebuf, sizeof(ebuf)); + if (handle == nullptr) { + return nullptr; + } + return os::dll_lookup(handle, name); +} + // Logging wrapper for MapViewOfFileEx static LPVOID mapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) { @@ -3250,9 +3260,9 @@ char* os::map_memory_to_file(char* base, size_t size, int fd) { assert(fd != -1, "File descriptor is not valid"); HANDLE fh = (HANDLE)_get_osfhandle(fd); - HANDLE fileMapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE, + HANDLE file_mapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE, (DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), nullptr); - if (fileMapping == nullptr) { + if (file_mapping == nullptr) { if (GetLastError() == ERROR_DISK_FULL) { vm_exit_during_initialization(err_msg("Could not allocate sufficient disk space for Java heap")); } @@ -3263,9 +3273,9 @@ char* os::map_memory_to_file(char* base, size_t size, int fd) { return nullptr; } - LPVOID addr = mapViewOfFileEx(fileMapping, FILE_MAP_WRITE, 0, 0, size, base); + LPVOID addr = mapViewOfFileEx(file_mapping, FILE_MAP_WRITE, 0, 0, size, base); - CloseHandle(fileMapping); + CloseHandle(file_mapping); return (char*)addr; } @@ -3278,40 +3288,75 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in return map_memory_to_file(base, size, fd); } +// VirtualAlloc2 / MapViewOfFile3 (Windows 1803+). Resolved in os::init_2() via lookup_kernelbase_symbol. +os::win32::VirtualAlloc2Fn os::win32::VirtualAlloc2 = nullptr; + +os::win32::MapViewOfFile3Fn os::win32::MapViewOfFile3 = nullptr; + +static bool is_VirtualAlloc2_supported() { + return os::win32::VirtualAlloc2 != nullptr; +} + +static bool is_MapViewOfFile3_supported() { + return os::win32::MapViewOfFile3 != nullptr; +} + // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { +static char* reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag) { assert(is_aligned(alignment, os::vm_allocation_granularity()), - "Alignment must be a multiple of allocation granularity (page size)"); + "Alignment must be a multiple of allocation granularity"); assert(is_aligned(size, os::vm_allocation_granularity()), - "Size must be a multiple of allocation granularity (page size)"); + "Size must be a multiple of allocation granularity"); size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); char* aligned_base = nullptr; - static const int max_attempts = 20; + constexpr int max_attempts = 20; for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { - char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, mem_tag) : - os::reserve_memory(extra_size, mem_tag); + char* extra_base = os::reserve_memory(extra_size, mem_tag); if (extra_base == nullptr) { return nullptr; } - // Do manual alignment aligned_base = align_up(extra_base, alignment); + os::release_memory(extra_base, extra_size); - if (file_desc != -1) { - os::unmap_memory(extra_base, extra_size); - } else { - os::release_memory(extra_base, extra_size); + // A racing thread may have taken this region instead of us, which is why we loop and retry. + aligned_base = os::attempt_reserve_memory_at(aligned_base, size, mem_tag); + } + + assert(aligned_base != nullptr, + "Did not manage to reserve after %d attempts (size %zu, alignment %zu)", max_attempts, size, alignment); + + return aligned_base; +} + +// Similar to reserve_memory_aligned, other reservation/mapping requests can race with this function. +static char* map_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + size_t extra_size = size + alignment; + assert(extra_size >= size, "overflow, size is too large to allow alignment"); + + char* aligned_base = nullptr; + constexpr int max_attempts = 20; + + for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { + char* extra_base = os::map_memory_to_file(extra_size, file_desc, mem_tag); + if (extra_base == nullptr) { + return nullptr; } + aligned_base = align_up(extra_base, alignment); + os::unmap_memory(extra_base, extra_size); - // Attempt to map, into the just vacated space, the slightly smaller aligned area. - // Which may fail, hence the loop. - aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag) : - os::attempt_reserve_memory_at(aligned_base, size, mem_tag); + // A racing thread may have taken this region instead of us, which is why we loop and retry. + aligned_base = os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag); } assert(aligned_base != nullptr, @@ -3320,6 +3365,84 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi return aligned_base; } +// MapViewOfFile3 supports alignment natively. +static char* map_memory_aligned_va2(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { + assert(file_desc != -1, "File descriptor should not be -1"); + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + MEM_ADDRESS_REQUIREMENTS requirements = {0}; + requirements.Alignment = alignment; + + MEM_EXTENDED_PARAMETER param = {0}; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &requirements; + + char* aligned_base = nullptr; + + // File-backed aligned mapping. + HANDLE fh = (HANDLE)_get_osfhandle(file_desc); + HANDLE file_mapping = CreateFileMapping(fh, nullptr, PAGE_READWRITE,(DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), nullptr); + DWORD err = GetLastError(); + if (file_mapping != nullptr) { + aligned_base = (char*)os::win32::MapViewOfFile3( + file_mapping, + GetCurrentProcess(), + nullptr, // let the system choose an aligned address + 0, // offset + size, + 0, // no special allocation type flags + PAGE_READWRITE, + ¶m, 1); + err = GetLastError(); + CloseHandle(file_mapping); + } + + if (aligned_base != nullptr) { + assert(is_aligned(aligned_base, alignment), "Result must be aligned"); + MemTracker::record_virtual_memory_reserve_and_commit(aligned_base, size, CALLER_PC, mem_tag); + return aligned_base; + } + log_trace(os)("Aligned allocation via MapViewOfFile3 failed, falling back to retry loop. GetLastError->%lu.", err); + return map_memory_aligned(size, alignment, file_desc, mem_tag); +} + +// VirtualAlloc2 supports alignment natively. +static char* reserve_memory_aligned_va2(size_t size, size_t alignment, MemTag mem_tag) { + assert(is_aligned(alignment, os::vm_allocation_granularity()), + "Alignment must be a multiple of allocation granularity"); + assert(is_aligned(size, os::vm_allocation_granularity()), + "Size must be a multiple of allocation granularity"); + + MEM_ADDRESS_REQUIREMENTS requirements = {0}; + requirements.Alignment = alignment; + + MEM_EXTENDED_PARAMETER param = {0}; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &requirements; + + char* aligned_base = nullptr; + + // Anonymous aligned reservation. + aligned_base = (char*)os::win32::VirtualAlloc2( + GetCurrentProcess(), + nullptr, // let the system choose an aligned address + size, + MEM_RESERVE, + PAGE_READWRITE, + ¶m, 1); + + if (aligned_base != nullptr) { + assert(is_aligned(aligned_base, alignment), "Result must be aligned"); + MemTracker::record_virtual_memory_reserve(aligned_base, size, CALLER_PC, mem_tag); + return aligned_base; + } + log_trace(os)("Aligned allocation via VirtualAlloc2 failed, falling back to retry loop. GetLastError->%lu.", GetLastError()); + return reserve_memory_aligned(size, alignment, mem_tag); +} + size_t os::commit_memory_limit() { BOOL is_in_job_object = false; BOOL res = IsProcessInJob(GetCurrentProcess(), nullptr, &is_in_job_object); @@ -3367,11 +3490,17 @@ size_t os::reserve_memory_limit() { char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) { // exec can be ignored - return map_or_reserve_memory_aligned(size, alignment, -1/* file_desc */, mem_tag); + if (is_VirtualAlloc2_supported()) { + return reserve_memory_aligned_va2(size, alignment, mem_tag); + } + return reserve_memory_aligned(size, alignment, mem_tag); } char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag) { - return map_or_reserve_memory_aligned(size, alignment, fd, mem_tag); + if (is_MapViewOfFile3_supported()) { + return map_memory_aligned_va2(size, alignment, fd, mem_tag); + } + return map_memory_aligned(size, alignment, fd, mem_tag); } char* os::pd_reserve_memory(size_t bytes, bool exec) { @@ -4588,21 +4717,21 @@ jint os::init_2(void) { // Lookup SetThreadDescription - the docs state we must use runtime-linking of // kernelbase.dll, so that is what we do. - HINSTANCE _kernelbase = LoadLibrary(TEXT("kernelbase.dll")); - if (_kernelbase != nullptr) { - _SetThreadDescription = - reinterpret_cast( - GetProcAddress(_kernelbase, - "SetThreadDescription")); + _SetThreadDescription = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("SetThreadDescription")); #ifdef ASSERT - _GetThreadDescription = - reinterpret_cast( - GetProcAddress(_kernelbase, - "GetThreadDescription")); + _GetThreadDescription = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("GetThreadDescription")); #endif - } log_info(os, thread)("The SetThreadDescription API is%s available.", _SetThreadDescription == nullptr ? " not" : ""); + // Prepare KernelBase APIs (VirtualAlloc2, MapViewOfFile3) if available (Windows version 1803). + os::win32::VirtualAlloc2 = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("VirtualAlloc2")); + os::win32::MapViewOfFile3 = reinterpret_cast( + os::win32::lookup_kernelbase_symbol("MapViewOfFile3")); + log_debug(os)("VirtualAlloc2 is%s available.", os::win32::VirtualAlloc2 == nullptr ? " not" : ""); + log_debug(os)("MapViewOfFile3 is%s available.", os::win32::MapViewOfFile3 == nullptr ? " not" : ""); return JNI_OK; } diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index d4a7d51c59b..5ebc80c817b 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -109,6 +109,19 @@ class os::win32 { // load dll from Windows system directory or Windows directory static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen); + // Resolve a symbol from KernelBase.dll, returns nullptr if not found. + static void* lookup_kernelbase_symbol(const char* name); + + // VirtualAlloc2 (since Windows version 1803) + // Resolved from KernelBase during os::init_2() or nullptr if unavailable. + typedef PVOID (WINAPI *VirtualAlloc2Fn)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + static VirtualAlloc2Fn VirtualAlloc2; + + // MapViewOfFile3 (since Windows version 1803) + // Resolved from KernelBase during os::init_2() or nullptr if unavailable. + typedef PVOID (WINAPI *MapViewOfFile3Fn)(HANDLE, HANDLE, PVOID, ULONG64, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + static MapViewOfFile3Fn MapViewOfFile3; + private: static void initialize_performance_counter(); diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index 0f79e7a5a69..a0cfe2a9893 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -31,7 +31,10 @@ #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/timerTrace.hpp" #include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" #include "utilities/ostream.hpp" #include "utilities/tableStatistics.hpp" @@ -239,10 +242,24 @@ void Dictionary::verify() { } void Dictionary::print_table_statistics(outputStream* st, const char* table_name) { - static TableStatistics ts; + TableStatistics stats; auto sz = [&] (InstanceKlass** val) { return sizeof(**val); }; - ts = _table->statistics_get(Thread::current(), sz, ts); - ts.print(st, table_name); + Thread* thread = Thread::current(); + ConcurrentTable::StatisticsTask sts(_table); + if (!sts.prepare(thread)) { + st->print_cr("Failed to take statistics"); + return; + } + TraceTime timer("GetStatistics", TRACETIME_LOG(Debug, perf)); + while (sts.do_task(thread, sz)) { + sts.pause(thread); + if (thread->is_Java_thread()) { + ThreadBlockInVM tbivm(JavaThread::cast(thread)); + } + sts.cont(thread); + } + stats = sts.done(thread); + stats.print(st, table_name); } diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index cec3586a50b..4a1b9ead116 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -527,6 +527,10 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_intpoly_assign: if (!UseIntPolyIntrinsics) return true; break; + case vmIntrinsics::_intpoly_mult_25519: + case vmIntrinsics::_intpoly_square_25519: + if (!UseIntPoly25519Intrinsics) return true; + break; case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: if (!UseCRC32CIntrinsics) return true; diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index de4eea669a1..8833e4167f6 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -549,6 +549,13 @@ class methodHandle; do_name(intPolyAssign_name, "conditionalAssign") \ do_signature(intPolyAssign_signature, "(I[J[J)V") \ \ + /* support for sun.security.util.math.intpoly.IntegerPolynomial25519 */ \ + do_class(sun_security_util_math_intpoly_IntegerPolynomial25519, "sun/security/util/math/intpoly/IntegerPolynomial25519") \ + do_intrinsic(_intpoly_mult_25519, sun_security_util_math_intpoly_IntegerPolynomial25519, intPolyMult_name, intPolyMult_signature, F_R) \ + do_intrinsic(_intpoly_square_25519, sun_security_util_math_intpoly_IntegerPolynomial25519, intPolySquare_name, intPolySquare_signature, F_R) \ + do_name(intPolySquare_name, "square") \ + do_signature(intPolySquare_signature, "([J[J)V") \ + \ /* support for java.util.Base64.Encoder*/ \ do_class(java_util_Base64_Encoder, "java/util/Base64$Encoder") \ do_intrinsic(_base64_encodeBlock, java_util_Base64_Encoder, encodeBlock_name, encodeBlock_signature, F_R) \ diff --git a/src/hotspot/share/gc/serial/cardTableRS.cpp b/src/hotspot/share/gc/serial/cardTableRS.cpp index a53ab066387..fe4977a809a 100644 --- a/src/hotspot/share/gc/serial/cardTableRS.cpp +++ b/src/hotspot/share/gc/serial/cardTableRS.cpp @@ -49,7 +49,14 @@ void CardTableRS::scan_old_to_young_refs(TenuredGeneration* tg, HeapWord* saved_ void CardTableRS::maintain_old_to_young_invariant(TenuredGeneration* old_gen, bool is_young_gen_empty) { if (is_young_gen_empty) { - clear_MemRegion(old_gen->prev_used_region()); + MemRegion prev_used_mr = old_gen->prev_used_region(); + if (!prev_used_mr.is_empty()) { + clear_MemRegion(prev_used_mr); + } + { + MemRegion old_gen_committed{old_gen->space()->bottom(), old_gen->space()->end()}; + verify_region(old_gen_committed, clean_card_val(), true); + } } else { MemRegion used_mr = old_gen->used_region(); MemRegion prev_used_mr = old_gen->prev_used_region(); @@ -59,7 +66,9 @@ void CardTableRS::maintain_old_to_young_invariant(TenuredGeneration* old_gen, } // No idea which card contains old-to-young pointer, so dirtying cards for // the entire used part of old-gen conservatively. - dirty_MemRegion(used_mr); + if (!used_mr.is_empty()) { + dirty_MemRegion(used_mr); + } } } diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 1ff6fd493a7..14bc320e32c 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -199,10 +199,9 @@ range(1, (INT_MAX - 1)) \ \ product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \ - "Ergonomically start one thread for this amount of " \ - "references for reference processing if " \ - "ParallelRefProcEnabled is true. Specify 0 to disable and " \ - "use all threads.") \ + "Ergonomically start one thread for this amount of references " \ + "for reference processing for parallel stop-the-world garbage " \ + "collectors. Specify 0 to force use of all available threads.") \ \ product(uint, InitiatingHeapOccupancyPercent, 45, \ "The percent occupancy (IHOP) of the current old generation " \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 07eb653bc94..08032b224d0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -1203,19 +1203,13 @@ void ShenandoahConcurrentGC::op_final_update_refs() { heap->verifier()->verify_roots_in_to_space(_generation); } - // If we are running in generational mode and this is an aging cycle, this will also age active - // regions that haven't been used for allocation. + // If we are running in generational mode, this will also age active regions that + // haven't been used for allocation. heap->update_heap_region_states(true /*concurrent*/); heap->set_update_refs_in_progress(false); heap->set_has_forwarded_objects(false); - if (heap->mode()->is_generational() && heap->is_concurrent_old_mark_in_progress()) { - // Aging_cycle is only relevant during evacuation cycle for individual objects and during final mark for - // entire regions. Both of these relevant operations occur before final update refs. - ShenandoahGenerationalHeap::heap()->set_aging_cycle(false); - } - if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify); heap->verifier()->verify_after_update_refs(_generation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 94f3409ac41..f522a33a31c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -53,8 +53,7 @@ ShenandoahGenerationalControlThread::ShenandoahGenerationalControlThread() : _requested_generation(nullptr), _gc_mode(none), _degen_point(ShenandoahGC::_degenerated_unset), - _heap(ShenandoahGenerationalHeap::heap()), - _age_period(0) { + _heap(ShenandoahGenerationalHeap::heap()) { shenandoah_assert_generational(); set_name("ShenControl"); create_and_start(); @@ -230,15 +229,6 @@ void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const } } -void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() { - if (_age_period-- == 0) { - _heap->set_aging_cycle(true); - _age_period = ShenandoahAgingCyclePeriod - 1; - } else { - _heap->set_aging_cycle(false); - } -} - void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest& request) { log_debug(gc, thread)("Starting GC (%s): %s, %s", gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name()); @@ -534,9 +524,6 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGen // At this point: // if (generation == YOUNG), this is a normal young cycle or a bootstrap cycle // if (generation == GLOBAL), this is a GLOBAL cycle - // In either case, we want to age old objects if this is an aging cycle - maybe_set_aging_cycle(); - ShenandoahGCSession session(cause, generation); TraceCollectorStats tcs(_heap->monitoring_support()->concurrent_collection_counters()); @@ -615,7 +602,6 @@ bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(Shenandoah void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause cause) { _heap->increment_total_collections(true); ShenandoahGCSession session(cause, _heap->global_generation()); - maybe_set_aging_cycle(); ShenandoahFullGC gc; gc.collect(cause); _degen_point = ShenandoahGC::_degenerated_unset; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 13e69d25268..5a3ab25eabe 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -80,9 +80,6 @@ private: // A reference to the heap ShenandoahGenerationalHeap* _heap; - // This is used to keep track of whether to age objects during the current cycle. - uint _age_period; - // This is true when the old generation cycle is in an interruptible phase (i.e., marking or // preparing for mark). ShenandoahSharedFlag _allow_old_preemption; @@ -142,9 +139,6 @@ private: void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); - // Configure the heap to age objects and regions if the aging period has elapsed. - void maybe_set_aging_cycle(); - // Take the _control_lock and check for a request to run a gc cycle. If a request is found, // the `prepare` methods are used to configure the heap and update heuristics accordingly. void check_for_request(ShenandoahGCRequest& request); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 1b11c696d18..43dbddda9f7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -312,11 +312,7 @@ void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) { // After full gc compaction, all regions have age 0. Embed the region's age into the object's age in order to preserve // tenuring progress. - if (_heap->is_aging_cycle()) { - ShenandoahHeap::increase_object_age(p, from_region_age + 1); - } else { - ShenandoahHeap::increase_object_age(p, from_region_age); - } + ShenandoahHeap::increase_object_age(p, from_region_age + 1); if (_young_compact_point + obj_size > _young_to_region->end()) { ShenandoahHeapRegion* new_to_region; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 4af2c9b1e5d..7170c88cd43 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -347,7 +347,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, uint oop copy_val = cast_to_oop(copy); // Update the age of the evacuated object - if (TO_GENERATION == YOUNG_GENERATION && is_aging_cycle()) { + if (TO_GENERATION == YOUNG_GENERATION) { increase_object_age(copy_val, from_region_age + 1); } @@ -975,7 +975,7 @@ public: // There have been allocations in this region since the start of the cycle. // Any objects new to this region must not assimilate elevated age. r->reset_age(); - } else if (ShenandoahGenerationalHeap::heap()->is_aging_cycle()) { + } else { r->increment_age(); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index d6893dc011e..91e5522de43 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -61,21 +61,10 @@ public: private: // ---------- Evacuations and Promotions - // - // True when regions and objects should be aged during the current cycle - ShenandoahSharedFlag _is_aging_cycle; // Age census used for adapting tenuring threshold ShenandoahAgeCensus* _age_census; public: - void set_aging_cycle(bool cond) { - _is_aging_cycle.set_cond(cond); - } - - inline bool is_aging_cycle() const { - return _is_aging_cycle.is_set(); - } - // Return the age census object for young gen ShenandoahAgeCensus* age_census() const { return _age_census; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index ad8cd220968..33d5fa6b04f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -66,7 +66,6 @@ class ShenandoahFreeSet; class ShenandoahConcurrentMark; class ShenandoahFullGC; class ShenandoahMonitoringSupport; -class ShenandoahPacer; class ShenandoahReferenceProcessor; class ShenandoahUncommitThread; class ShenandoahVerifier; @@ -534,7 +533,6 @@ private: ShenandoahCollectorPolicy* _shenandoah_policy; ShenandoahMode* _gc_mode; ShenandoahFreeSet* _free_set; - ShenandoahPacer* _pacer; ShenandoahVerifier* _verifier; ShenandoahPhaseTimings* _phase_timings; @@ -559,7 +557,6 @@ public: ShenandoahCollectorPolicy* shenandoah_policy() const { return _shenandoah_policy; } ShenandoahMode* mode() const { return _gc_mode; } ShenandoahFreeSet* free_set() const { return _free_set; } - ShenandoahPacer* pacer() const { return _pacer; } ShenandoahPhaseTimings* phase_timings() const { return _phase_timings; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index aa6b71a7c50..3647a818490 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -529,10 +529,6 @@ "Allow young generation collections to suspend concurrent" \ " marking in the old generation.") \ \ - product(uintx, ShenandoahAgingCyclePeriod, 1, EXPERIMENTAL, \ - "With generational mode, increment the age of objects and" \ - "regions each time this many young-gen GC cycles are completed.") \ - \ develop(bool, ShenandoahEnableCardStats, false, \ "Enable statistics collection related to clean & dirty cards") \ \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 2f48fffcaa2..bf434030499 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -819,6 +819,8 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_poly1305_processBlocks: case vmIntrinsics::_intpoly_montgomeryMult_P256: case vmIntrinsics::_intpoly_assign: + case vmIntrinsics::_intpoly_mult_25519: + case vmIntrinsics::_intpoly_square_25519: case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 49e59c70c47..f561818a99b 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2272,6 +2272,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "poly1305_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "intpoly_montgomeryMult_P256") == 0 || strcmp(call->as_CallLeaf()->_name, "intpoly_assign") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_mult_25519") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_square_25519") == 0 || strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "chacha20Block") == 0 || strcmp(call->as_CallLeaf()->_name, "kyberNtt") == 0 || diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 7251783d771..adb8ff2dedb 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -666,6 +666,10 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_intpoly_montgomeryMult_P256(); case vmIntrinsics::_intpoly_assign: return inline_intpoly_assign(); + case vmIntrinsics::_intpoly_mult_25519: + return inline_intpoly_mult_25519(); + case vmIntrinsics::_intpoly_square_25519: + return inline_intpoly_square_25519(); case vmIntrinsics::_encodeISOArray: case vmIntrinsics::_encodeByteISOArray: return inline_encodeISOArray(false); @@ -8373,6 +8377,70 @@ bool LibraryCallKit::inline_intpoly_assign() { return true; } +bool LibraryCallKit::inline_intpoly_mult_25519() { + address stubAddr; + const char *stubName; + assert(UseIntPoly25519Intrinsics, "need intpoly25519 intrinsics support"); + assert(callee()->signature()->size() == 3, "intpoly_mult_25519 has %d parameters", callee()->signature()->size()); + stubAddr = StubRoutines::intpoly_mult_25519(); + stubName = "intpoly_mult_25519"; + + if (!stubAddr) return false; + null_check_receiver(); // null-check receiver + if (stopped()) return true; + + Node* a = argument(1); + Node* b = argument(2); + Node* r = argument(3); + + a = must_be_not_null(a, true); + b = must_be_not_null(b, true); + r = must_be_not_null(r, true); + + Node* a_start = array_element_address(a, intcon(0), T_LONG); + assert(a_start, "a array is null"); + Node* b_start = array_element_address(b, intcon(0), T_LONG); + assert(b_start, "b array is null"); + Node* r_start = array_element_address(r, intcon(0), T_LONG); + assert(r_start, "r array is null"); + + Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, + OptoRuntime::intpoly_mult_25519_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, b_start, r_start); + return true; +} + +bool LibraryCallKit::inline_intpoly_square_25519() { + address stubAddr; + const char *stubName; + assert(UseIntPoly25519Intrinsics, "need intpoly25519 intrinsics support"); + assert(callee()->signature()->size() == 2, "intpoly_mult_25519 has %d parameters", callee()->signature()->size()); + stubAddr = StubRoutines::intpoly_square_25519(); + stubName = "intpoly_square_25519"; + + if (!stubAddr) return false; + null_check_receiver(); // null-check receiver + if (stopped()) return true; + + Node* a = argument(1); + Node* r = argument(2); + + a = must_be_not_null(a, true); + r = must_be_not_null(r, true); + + Node* a_start = array_element_address(a, intcon(0), T_LONG); + assert(a_start, "a array is null"); + Node* r_start = array_element_address(r, intcon(0), T_LONG); + assert(r_start, "r array is null"); + + Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, + OptoRuntime::intpoly_square_25519_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, r_start); + return true; +} + //------------------------------inline_digestBase_implCompress----------------------- // // Calculate MD5 for single-block byte[] array. diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 5b46ae832a4..871a6b0d072 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -343,6 +343,8 @@ class LibraryCallKit : public GraphKit { bool inline_poly1305_processBlocks(); bool inline_intpoly_montgomeryMult_P256(); bool inline_intpoly_assign(); + bool inline_intpoly_mult_25519(); + bool inline_intpoly_square_25519(); bool inline_digestBase_implCompress(vmIntrinsics::ID id); bool inline_keccak(vmIntrinsics::ID id); bool inline_digestBase_implCompressMB(int predicate); diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 1afffcadd6e..7f791082b65 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -237,6 +237,8 @@ const TypeFunc* OptoRuntime::_string_IndexOf_Type = nullptr; const TypeFunc* OptoRuntime::_poly1305_processBlocks_Type = nullptr; const TypeFunc* OptoRuntime::_intpoly_montgomeryMult_P256_Type = nullptr; const TypeFunc* OptoRuntime::_intpoly_assign_Type = nullptr; +const TypeFunc* OptoRuntime::_intpoly_mult_25519_Type = nullptr; +const TypeFunc* OptoRuntime::_intpoly_square_25519_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesCRC32_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesCRC32C_Type = nullptr; const TypeFunc* OptoRuntime::_updateBytesAdler32_Type = nullptr; @@ -1786,6 +1788,41 @@ static const TypeFunc* make_intpoly_assign_Type() { return TypeFunc::make(domain, range); } +static const TypeFunc* make_intpoly_mult_25519_Type() { + int argcnt = 3; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a array + fields[argp++] = TypePtr::NOTNULL; // b array + fields[argp++] = TypePtr::NOTNULL; // r(esult) array + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = nullptr; // void + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + +static const TypeFunc* make_intpoly_square_25519_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a array + fields[argp++] = TypePtr::NOTNULL; // r(esult) array + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = nullptr; // void + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + //------------- Interpreter state for on stack replacement static const TypeFunc* make_osr_end_Type() { // create input type (domain) @@ -2354,6 +2391,8 @@ void OptoRuntime::initialize_types() { _poly1305_processBlocks_Type = make_poly1305_processBlocks_Type(); _intpoly_montgomeryMult_P256_Type = make_intpoly_montgomeryMult_P256_Type(); _intpoly_assign_Type = make_intpoly_assign_Type(); + _intpoly_mult_25519_Type = make_intpoly_mult_25519_Type(); + _intpoly_square_25519_Type = make_intpoly_square_25519_Type(); _updateBytesCRC32_Type = make_updateBytesCRC32_Type(); _updateBytesCRC32C_Type = make_updateBytesCRC32C_Type(); _updateBytesAdler32_Type = make_updateBytesAdler32_Type(); diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index af8a206e10c..5802bf59ae5 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -190,6 +190,8 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _poly1305_processBlocks_Type; static const TypeFunc* _intpoly_montgomeryMult_P256_Type; static const TypeFunc* _intpoly_assign_Type; + static const TypeFunc* _intpoly_mult_25519_Type; + static const TypeFunc* _intpoly_square_25519_Type; static const TypeFunc* _updateBytesCRC32_Type; static const TypeFunc* _updateBytesCRC32C_Type; static const TypeFunc* _updateBytesAdler32_Type; @@ -687,6 +689,18 @@ private: return _intpoly_assign_Type; } + // IntegerPolynomial25519 multiply function + static inline const TypeFunc* intpoly_mult_25519_Type() { + assert(_intpoly_mult_25519_Type != nullptr, "should be initialized"); + return _intpoly_mult_25519_Type; + } + + // IntegerPolynomial25519 square function + static inline const TypeFunc* intpoly_square_25519_Type() { + assert(_intpoly_square_25519_Type != nullptr, "should be initialized"); + return _intpoly_square_25519_Type; + } + /** * int updateBytesCRC32(int crc, byte* b, int len) */ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index dc177bdce6d..2804224ed01 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -544,25 +544,6 @@ static SpecialFlag const special_jvm_flags[] = { { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(27), JDK_Version::undefined() }, #endif - { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NewSizeThreadIncrease", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NeverActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AlwaysActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseXMMForArrayCopy", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseNewLongLShift", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AggressiveHeap", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - - {"ShenandoahAccelerationSamplePeriod", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahRateAccelerationSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahMomentaryAllocationRateSpikeSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleFrequencyHz", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleSizeSeconds", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveInitialSpikeThreshold",JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveDecayFactor", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index a1c33f4fda0..b983b4648d4 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1237,9 +1237,6 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { #ifndef PRODUCT -// Returns true iff the address p is readable and *(intptr_t*)p != errvalue -extern "C" bool dbg_is_safe(const void* p, intptr_t errvalue); - class FrameValuesOopClosure: public OopClosure, public DerivedOopClosure { private: GrowableArray* _oops; @@ -1269,17 +1266,13 @@ public: _derived->push(derived_loc); } - bool is_good(oop* p) { - return *p == nullptr || (dbg_is_safe(*p, -1) && dbg_is_safe((*p)->klass_without_asserts(), -1) && oopDesc::is_oop_or_null(*p)); - } void describe(FrameValues& values, int frame_no) { for (int i = 0; i < _oops->length(); i++) { oop* p = _oops->at(i); - values.describe(frame_no, (intptr_t*)p, err_msg("oop%s for #%d", is_good(p) ? "" : " (BAD)", frame_no)); + values.describe(frame_no, (intptr_t*)p, err_msg("oop for #%d", frame_no)); } for (int i = 0; i < _narrow_oops->length(); i++) { narrowOop* p = _narrow_oops->at(i); - // we can't check for bad compressed oops, as decoding them might crash values.describe(frame_no, (intptr_t*)p, err_msg("narrow oop for #%d", frame_no)); } assert(_base->length() == _derived->length(), "should be the same"); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index f90a644eaa4..ec34305f837 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -229,9 +229,13 @@ const int ObjectAlignmentInBytes = 8; \ product(bool, UsePoly1305Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for sun.security.util.math.intpoly") \ - product(bool, UseIntPolyIntrinsics, false, DIAGNOSTIC, \ + \ + product(bool, UseIntPolyIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for sun.security.util.math.intpoly.MontgomeryIntegerPolynomialP256") \ \ + product(bool, UseIntPoly25519Intrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for sun.security.util.math.intpoly.IntegerPolynomial25519") \ + \ product(size_t, LargePageSizeInBytes, 0, \ "Maximum large page size used (0 will use the default large " \ "page size for the environment as the maximum) " \ diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index bef6a0c27f0..5c3567eb0c0 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -801,6 +801,12 @@ intpoly_montgomeryMult_P256, intpoly_montgomeryMult_P256) \ do_stub(compiler, intpoly_assign) \ do_entry(compiler, intpoly_assign, intpoly_assign, intpoly_assign) \ + do_stub(compiler, intpoly_mult_25519) \ + do_entry(compiler, intpoly_mult_25519, \ + intpoly_mult_25519, intpoly_mult_25519) \ + do_stub(compiler, intpoly_square_25519) \ + do_entry(compiler, intpoly_square_25519, \ + intpoly_square_25519, intpoly_square_25519) \ do_stub(compiler, md5_implCompress) \ do_entry(compiler, md5_implCompress, md5_implCompress, \ md5_implCompress) \ diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index 97ceb19d0ad..b720871c389 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -654,17 +654,20 @@ public: // VM.systemdictionary -verbose: for dumping the system dictionary table // class VM_DumpHashtable : public VM_Operation { +public: + enum DumpKind { + DumpSymbols, + DumpStrings, + DumpSysDict + }; + private: outputStream* _out; - int _which; + DumpKind _which; bool _verbose; + public: - enum { - DumpSymbols = 1 << 0, - DumpStrings = 1 << 1, - DumpSysDict = 1 << 2 // not implemented yet - }; - VM_DumpHashtable(outputStream* out, int which, bool verbose) { + VM_DumpHashtable(outputStream* out, DumpKind which, bool verbose) { _out = out; _which = which; _verbose = verbose; diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index d2317847307..dfba84ca519 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -534,11 +534,6 @@ class ConcurrentHashTable : public CHeapObj { template void bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f); - // Gets statistics if available, if not return old one. Item sizes are calculated with - // VALUE_SIZE_FUNC. - template - TableStatistics statistics_get(Thread* thread, VALUE_SIZE_FUNC& vs_f, TableStatistics old); - // Moves all nodes from this table to to_cht with new hash code. // Must be done at a safepoint. void rehash_nodes_to(Thread* thread, ConcurrentHashTable* to_cht); diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index d5f6dee336b..312d118a647 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -1266,22 +1266,6 @@ inline TableStatistics ConcurrentHashTable:: } } -template -template -inline TableStatistics ConcurrentHashTable:: - statistics_get(Thread* thread, VALUE_SIZE_FUNC& vs_f, TableStatistics old) -{ - if (!try_resize_lock(thread)) { - return old; - } - InternalTable* table = get_table(); - NumberSeq summary; - size_t literal_bytes = 0; - - internal_statistics_range(thread, 0, table->_size, vs_f, summary, literal_bytes); - return internal_statistics_epilog(thread, summary, literal_bytes); -} - template inline void ConcurrentHashTable:: rehash_nodes_to(Thread* thread, ConcurrentHashTable* to_cht) diff --git a/src/java.base/share/classes/java/text/ListFormat.java b/src/java.base/share/classes/java/text/ListFormat.java index 3f320bbcc9b..29e58ea717c 100644 --- a/src/java.base/share/classes/java/text/ListFormat.java +++ b/src/java.base/share/classes/java/text/ListFormat.java @@ -84,9 +84,9 @@ import sun.util.locale.provider.LocaleProviderAdapter; * Note: these examples are from CLDR, there could be different results from other locale providers. *

* Alternatively, Locale, Type, and/or Style independent instances - * can be created with {@link #getInstance(String[])}. The String array to the - * method specifies the delimiting patterns for the start/middle/end portion of - * the formatted string, as well as optional specialized patterns for two or three + * can be created with {@link #getInstance(String[])}. The String array passed to the + * method specifies the delimiting patterns for the {@code start}/{@code middle}/{@code end} + * portion of the formatted string, as well as optional specialized patterns for two or three * elements. Refer to the method description for more detail. *

* On parsing, if some ambiguity is found in the input string, such as delimiting @@ -121,7 +121,8 @@ public final class ListFormat extends Format { /** * The array of five pattern Strings. Each element corresponds to the Unicode LDML's - * `listPatternsPart` type, i.e, start/middle/end/two/three. + * {@code listPatternPart} type, i.e, + * {@code start}/{@code middle}/{@code end}/{@code two}/{@code three}. * @serial */ private final String[] patterns; @@ -153,6 +154,7 @@ public final class ListFormat extends Format { var pattern = patterns[START]; var placeholderPositions = findPlaceholders(pattern); if (placeholderPositions != null && + placeholderPositions[2] == -1 && placeholderPositions[1] + PLACEHOLDER_LENGTH == pattern.length()) { startBefore = pattern.substring(0, placeholderPositions[0]); startBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, @@ -164,6 +166,7 @@ public final class ListFormat extends Format { pattern = patterns[MIDDLE]; placeholderPositions = findPlaceholders(pattern); if (placeholderPositions != null && + placeholderPositions[2] == -1 && placeholderPositions[0] == 0 && placeholderPositions[1] + PLACEHOLDER_LENGTH == pattern.length()) { middleBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, @@ -174,7 +177,9 @@ public final class ListFormat extends Format { pattern = patterns[END]; placeholderPositions = findPlaceholders(pattern); - if (placeholderPositions != null && placeholderPositions[0] == 0) { + if (placeholderPositions != null && + placeholderPositions[2] == -1 && + placeholderPositions[0] == 0) { endBetween = pattern.substring(placeholderPositions[0] + PLACEHOLDER_LENGTH, placeholderPositions[1]); endAfter = pattern.substring(placeholderPositions[1] + PLACEHOLDER_LENGTH); @@ -185,7 +190,8 @@ public final class ListFormat extends Format { // Validate two/three patterns, if given. Otherwise, generate them pattern = patterns[TWO]; if (!pattern.isEmpty()) { - if (findPlaceholders(pattern) == null) { + placeholderPositions = findPlaceholders(pattern); + if (placeholderPositions == null || placeholderPositions[2] >= 0) { throw new IllegalArgumentException("pattern for two is incorrect: " + pattern); } } else { @@ -245,36 +251,43 @@ public final class ListFormat extends Format { * instead of letting the runtime provide appropriate patterns for the {@code Locale}, * {@code Type}, or {@code Style}. *

- * The patterns array should contain five String patterns, each corresponding to the Unicode LDML's - * {@code listPatternPart}, i.e., "start", "middle", "end", two element, and three element patterns - * in this order. Each pattern contains "{0}" and "{1}" (and "{2}" for the three element pattern) - * placeholders that are substituted with the passed input strings on formatting. - * If the length of the patterns array is not 5, an {@code IllegalArgumentException} - * is thrown. + * The patterns array should contain five String patterns, each corresponding + * to the Unicode LDML's {@code listPatternPart}, i.e., {@code start}, + * {@code middle}, {@code end}, {@code two} element, and {@code three} + * element patterns in this order. Each pattern contains "{0}" and "{1}" + * (and "{2}" for the {@code three} element pattern) placeholders that are + * substituted with the passed input strings on formatting. If the length of + * the patterns array is not 5, an {@code IllegalArgumentException} is thrown. *

* Each pattern string is first parsed as follows. Literals in parentheses, such as * "start_before", are optional: - *

+     * {@snippet :
      * start := (start_before){0}start_between{1}
      * middle := {0}middle_between{1}
      * end := {0}end_between{1}(end_after)
      * two := (two_before){0}two_between{1}(two_after)
      * three := (three_before){0}three_between1{1}three_between2{2}(three_after)
-     * 
- * If two or three pattern string is empty, it falls back to - * {@code "(start_before){0}end_between{1}(end_after)"}, - * {@code "(start_before){0}start_between{1}end_between{2}(end_after)"} respectively. - * If parsing of any pattern string for start, middle, end, two, or three fails, + * } + * If the {@code two} or {@code three} pattern string is empty, it falls back to + * {@snippet : + * (start_before){0}end_between{1}(end_after) + * (start_before){0}start_between{1}end_between{2}(end_after) + * } + * respectively. + * If parsing of any pattern string for {@code start}, {@code middle}, + * {@code end}, {@code two}, or {@code three} fails, including duplicate + * placeholders, "{2}" in patterns other than the {@code three} element + * pattern, or any use of "{" or "}" other than "{0}", "{1}", or "{2}", * it throws an {@code IllegalArgumentException}. *

* On formatting, the input string list with {@code n} elements substitutes above * placeholders based on the number of elements: - *

+     * {@snippet :
      * n = 1: {0}
      * n = 2: parsed pattern for "two"
      * n = 3: parsed pattern for "three"
      * n > 3: (start_before){0}start_between{1}middle_between{2} ... middle_between{m}end_between{n}(end_after)
-     * 
+ * } * As an example, the following table shows a pattern array which is equivalent to * {@code STANDARD} type, {@code FULL} style in US English: * @@ -664,15 +677,37 @@ public final class ListFormat extends Format { /** * {@return the positions of the "{0}", "{1}", and "{2}" placeholders in the * given pattern string, or null if the pattern is invalid} + * Only "{0}", "{1}", or "{2}" placeholders are allowed. Any other use of + * curly braces is not allowed. * * The returned array contains -1 for "{2}" if that placeholder is absent. * * @param pattern pattern string to parse */ private static int[] findPlaceholders(String pattern) { - var positions = new int[3]; - for (int i = 0; i < positions.length; i++) { - positions[i] = pattern.indexOf("{" + i + "}"); + var positions = new int[] {-1, -1, -1}; + + for (int i = 0; i < pattern.length(); i++) { + var ch = pattern.charAt(i); + if (ch == '{') { + if (i + PLACEHOLDER_LENGTH > pattern.length() || + pattern.charAt(i + 1) < '0' || + pattern.charAt(i + 1) > '2' || + pattern.charAt(i + 2) != '}') { + return null; + } + + // Check for duplicate placeholders + var index = pattern.charAt(i + 1) - '0'; + if (positions[index] != -1) { + return null; + } + + positions[index] = i; + i += PLACEHOLDER_LENGTH - 1; + } else if (ch == '}') { + return null; + } } // Check the existence and order of the placeholders diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 137cac45ed0..f39d92aeeb4 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -418,19 +418,15 @@ public abstract class ForkJoinTask implements Future, Serializable { for (;;) { if ((s = status) < 0) break; - else if (interrupts < 0) { - s = ABNORMAL; // interrupted and not done - break; - } else if (Thread.interrupted()) { - if (!ForkJoinPool.poolIsStopping(pool)) - interrupts = interruptible ? -1 : 1; - else { - interrupts = 1; // re-assert if cleared + if (ForkJoinPool.poolIsStopping(pool)) { try { cancel(true); - } catch (Throwable ignore) { - } + } catch (Throwable ignore) { } + } + if ((interrupts = interruptible ? -1 : 1) < 0) { + s = ABNORMAL; + break; } } else if (deadline != 0L) { diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java index c8f23da417e..b7b1ddae0e0 100644 --- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java @@ -26,6 +26,7 @@ package sun.security.util.math.intpoly; import java.math.BigInteger; +import jdk.internal.vm.annotation.IntrinsicCandidate; public final class IntegerPolynomial25519 extends IntegerPolynomial { private static final int BITS_PER_LIMB = 51; @@ -235,6 +236,7 @@ public final class IntegerPolynomial25519 extends IntegerPolynomial { * @param b [in] the limb operand to multiply. * @param r [out] the product of the limbs operands that is fully reduced. */ + @IntrinsicCandidate protected void mult(long[] a, long[] b, long[] r) { long aa0 = a[0]; long aa1 = a[1]; @@ -414,6 +416,7 @@ public final class IntegerPolynomial25519 extends IntegerPolynomial { * @param a [in] the limb operand to square. * @param r [out] the resulting square of the limb which is fully reduced. */ + @IntrinsicCandidate protected void square(long[] a, long[] r) { long aa0 = a[0]; long aa1 = a[1]; diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 70824046824..ef99084018d 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -2997,14 +2997,6 @@ they're used. : Enables the use of Java Flight Recorder (JFR) during the runtime of the application. Since JDK 8u40 this option has not been required to use JFR. -[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} -: Enables parallel reference processing. By default, collectors employing multiple - threads perform parallel reference processing if the number of parallel threads - to use is larger than one. - The option is available only when the throughput or G1 garbage collector is used - (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple - threads always perform reference processing in parallel. - ## Obsolete Java Options These `java` options are still accepted but ignored, and a warning is issued @@ -3017,6 +3009,18 @@ when they're used. 396](https://openjdk.org/jeps/396) and made obsolete in JDK 17 by [JEP 403](https://openjdk.org/jeps/403). +## Removed Java Options + +These `java` options have been removed in JDK @@VERSION_SPECIFICATION@@ and using them results in an error of: + +> `Unrecognized VM option` *option-name* + +[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} +: Enabled Java heap optimization. This set various parameters to be + optimal for long-running jobs with intensive memory allocation, based on + the configuration of the computer (RAM and CPU). By default, the option + was disabled and the heap sizes configured less aggressively. + [`-XX:+NeverActAsServerClassMachine`]{#-XX__NeverActAsServerClassMachine} : Enabled the "Client VM emulation" mode, which used only the C1 JIT compiler, a 32Mb CodeCache, and the Serial GC. The maximum amount of memory that the @@ -3037,18 +3041,18 @@ when they're used. -XX:{+|-}UseJVMCICompiler ``` -[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} -: Enabled Java heap optimization. This set various parameters to be - optimal for long-running jobs with intensive memory allocation, based on - the configuration of the computer (RAM and CPU). By default, the option - was disabled and the heap sizes configured less aggressively. - -## Removed Java Options - -No documented java options have been removed in JDK @@VERSION_SPECIFICATION@@. +[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} +: Enables parallel reference processing. By default, collectors employing multiple + threads perform parallel reference processing if the number of parallel threads + to use is larger than one. + The option is available only when the throughput or G1 garbage collector is used + (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple + threads always perform reference processing in parallel. For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in: +- [The `java` Command, Release 27](https://docs.oracle.com/en/java/javase/27/docs/specs/man/java.html) + - [The `java` Command, Release 26](https://docs.oracle.com/en/java/javase/26/docs/specs/man/java.html) - [The `java` Command, Release 25](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java index 6121a0c1673..c4573317785 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -351,4 +351,9 @@ class Http2ClientImpl { public boolean stopping() { return stopping; } + + // getConnections() is used only by tests. + Map getConnections() { + return connections; + } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 94b8505da47..11022ca5c96 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -52,7 +52,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.function.Supplier; @@ -1610,16 +1609,37 @@ class Http2Connection implements Closeable { return frames; } - // Dedicated cache for headers encoding ByteBuffer. + // Dedicated reusable ByteBuffer for headers encoding. // There can be no concurrent access to this buffer as all access to this buffer // and its content happen within a single critical code block section protected - // by the sendLock. / (see sendFrame()) - // private final ByteBufferPool headerEncodingPool = new ByteBufferPool(); + // by the sendlock (see sendFrame()). + private ByteBuffer cachedHeaderBuffer; + + // getCachedHeaderBuffer() is used only by tests and it should not be + // called in source code without also holding `sendlock`. + ByteBuffer getCachedHeaderBuffer() { + return cachedHeaderBuffer; + } private ByteBuffer getHeaderBuffer(int size) { - ByteBuffer buf = ByteBuffer.allocate(size); - buf.limit(size); - return buf; + assert sendlock.isHeldByCurrentThread() : "current thread is not holding sendlock"; + + if (cachedHeaderBuffer == null || cachedHeaderBuffer.capacity() < size) { + cachedHeaderBuffer = ByteBuffer.allocate(size); + return cachedHeaderBuffer; + } + + cachedHeaderBuffer.clear(); + cachedHeaderBuffer.limit(size); + return cachedHeaderBuffer; + } + + private static ByteBuffer copyBuffer(ByteBuffer buffer) { + buffer.flip(); + ByteBuffer copy = ByteBuffer.allocate(buffer.remaining()); + copy.put(buffer); + copy.flip(); + return copy; } /* @@ -1634,8 +1654,8 @@ class Http2Connection implements Closeable { * encoding in HTTP/2... */ private List encodeHeadersImpl(int bufferSize, HttpHeaders... headers) { - ByteBuffer buffer = getHeaderBuffer(bufferSize); List buffers = new ArrayList<>(); + ByteBuffer buffer = getHeaderBuffer(bufferSize); for (HttpHeaders header : headers) { for (Map.Entry> e : header.map().entrySet()) { String lKey = e.getKey().toLowerCase(Locale.US); @@ -1644,16 +1664,17 @@ class Http2Connection implements Closeable { hpackOut.header(lKey, value); while (!hpackOut.encode(buffer)) { if (!buffer.hasRemaining()) { - buffer.flip(); - buffers.add(buffer); - buffer = getHeaderBuffer(bufferSize); + ByteBuffer copy = copyBuffer(buffer); + buffers.add(copy); + buffer.clear(); + buffer.limit(bufferSize); } } } } } - buffer.flip(); - buffers.add(buffer); + ByteBuffer copy = copyBuffer(buffer); + buffers.add(copy); return buffers; } @@ -1710,7 +1731,7 @@ class Http2Connection implements Closeable { } } - private final Lock sendlock = new ReentrantLock(); + private final ReentrantLock sendlock = new ReentrantLock(); void sendFrame(Http2Frame frame) { try { diff --git a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java index 6446473d9d6..362368cb2c5 100644 --- a/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java +++ b/src/jdk.attach/share/classes/com/sun/tools/attach/spi/AttachProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -58,8 +58,8 @@ import java.util.ServiceLoader; * for example, ships with attach providers that use the package name "sun" * (for historical reasons). The * type typically corresponds to the attach mechanism. For example, an - * implementation that uses the Doors inter-process communication mechanism - * might use the type "doors". The purpose of the name and type is to + * implementation that uses the UNIX Domain Socket inter-process communication mechanism + * might use the type "socket". The purpose of the name and type is to * identify providers in environments where there are multiple providers * installed. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java index 15f55d18cc0..c1c4dd512d6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -137,6 +137,26 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite .title(title))); } + /** + * Returns a label for the given element to be used the table of contents sidebar. + * + * @param executableElement method or constructor + * @return the link label + */ + protected Content getTOCLabel(ExecutableElement executableElement) { + var signature = utils.makeSignature(executableElement, typeElement, false, true); + var label = new ContentBuilder(Text.of(utils.getSimpleName(executableElement))); + // Insert line break opportunity before first parameter. + if (signature.length() > 2) { + label.add(Text.of(signature.substring(0, 1))) + .add(HtmlTree.WBR()) + .add(Text.of(signature.substring(1))); + } else { + label.add(signature); + } + return label; + } + /** * Adds the generic type parameters. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java index d8d01a4e6ad..48e269445ae 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java @@ -119,9 +119,7 @@ public class ConstructorWriter extends AbstractExecutableMemberWriter { constructorContent.add(div); memberList.add(getMemberListItem(constructorContent)); writer.tableOfContents.addLink(htmlIds.forMember(currentConstructor).getFirst(), - Text.of(utils.getSimpleName(constructor) - + utils.makeSignature(currentConstructor, typeElement, false, true)), - TableOfContents.Level.SECOND); + getTOCLabel(currentConstructor), TableOfContents.Level.SECOND); } Content constructorDetails = getConstructorDetails(constructorDetailsHeader, memberList); target.add(constructorDetails); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java index 3bc5b7617b0..5edfd9e174d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriter.java @@ -118,9 +118,7 @@ public class MethodWriter extends AbstractExecutableMemberWriter { methodContent.add(div); memberList.add(writer.getMemberListItem(methodContent)); writer.tableOfContents.addLink(htmlIds.forMember(currentMethod).getFirst(), - Text.of(utils.getSimpleName(method) - + utils.makeSignature(currentMethod, typeElement, false, true)), - TableOfContents.Level.SECOND); + getTOCLabel(currentMethod), TableOfContents.Level.SECOND); } Content methodDetails = getMethodDetails(methodDetailsHeader, memberList); detailsList.add(methodDetails); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index fc0fa68f029..12b441727c6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -82,6 +82,8 @@ /* Search input colors */ --search-input-background-color: #ffffff; --search-input-text-color: #000000; + --search-border-light-color: #eaeaea; + --search-border-dark-color: #a6a6a6; --search-input-placeholder-color: #757575; --overlay-background: rgba(153, 169, 183, 0.3); /* Highlight color for active search tag target */ @@ -107,23 +109,23 @@ :root[data-theme="theme-dark"] { --body-text-color: #e8e8e8; --block-text-color: #e8e8e8; - --body-background-color: #1f2124; + --body-background-color: #202226; --section-background-color: var(--body-background-color); --detail-background-color: var(--body-background-color); --code-background-color: #303940; --mark-background-color: #313131; --detail-block-color: #31363c; - --navbar-background-color: #395A6F; + --navbar-background-color: #406074; --navbar-text-color: #ffffff; - --subnav-background-color: #3d454d; + --subnav-background-color: #434c54; --subnav-link-color: #d8dcdf; --member-heading-background-color: var(--subnav-background-color); --selected-background-color: #f8981d; --selected-text-color: #253441; --selected-link-color: #4a698a; --table-header-color: #38444d; - --even-row-color: #222528; - --odd-row-color: #2d3135; + --even-row-color: #282c2f; + --odd-row-color: #33383b; --title-color: #fff; --link-color: #94badb; --link-color-active: #e8a351; @@ -138,8 +140,10 @@ --border-color: #444444; --table-border-color: #717171; --tab-border-radius: 2px 2px 0 0; - --search-input-background-color: #303030; + --search-input-background-color: #202224; --search-input-text-color: #d0d0d0; + --search-border-light-color: #505050; + --search-border-dark-color: #000000; --search-input-placeholder-color: #979797; --overlay-background: rgba(0, 0, 0, 0.45); --search-tag-background-color: #c6c61e; @@ -192,7 +196,7 @@ body { width:100%; } main [id] { - scroll-margin-top: calc(var(--nav-height) + 6px); + scroll-margin-top: calc(var(--nav-height) + 14px); } div.main-grid { max-width: var(--max-content-width); @@ -246,6 +250,9 @@ h1, h2, h3, h4, h5, h6, div.member-signature, div.member-signature > span { ul { list-style-type:disc; } +main li { + margin-top: 4px; +} tt { font-family:var(--code-font-family); } @@ -486,12 +493,7 @@ body.class-declaration-page .details h3 { } body.class-declaration-page section.detail:target > h3, body.class-declaration-page section.detail > h3:target { - background-color: var(--navbar-background-color); - color: var(--navbar-text-color); -} -body.class-declaration-page section.detail:target > h3 > a.anchor-link > img, -body.class-declaration-page section.detail > h3:target > a.anchor-link > img { - filter: invert(100%) brightness(160%); + box-shadow: -4px 0 0 rgb(from var(--link-color) r g b / 0.7); } h1 > sup { font-size: small; @@ -522,6 +524,9 @@ section.class-description > div.horizontal-scroll > :is(dl, ol, ul, p, div, bloc section.class-description > div.horizontal-scroll > :last-child > :is(li, dd):last-child { margin-bottom:4px; } +dl.notes { + margin-top: 14.2px; +} dl.notes > dt { font-family: var(--body-font-family); font-size:0.856em; @@ -661,9 +666,12 @@ a.current-selection { } nav.toc a { display: block; - padding: 8px; + padding: 7px 8px; overflow: hidden; text-overflow: ellipsis; + text-wrap: balance; + text-indent: 0.5em hanging; + line-height: 1.35; } nav.toc ol.toc-list ol.toc-list a { padding-left: 24px; @@ -737,11 +745,13 @@ ul.tag-list li { display: inline; } ul.tag-list li:not(:last-child):after, -ul.tag-list-long li:not(:last-child):after -{ +ul.tag-list-long li:not(:last-child):after { content: ", "; white-space: pre-wrap; } +ul.tag-list-long > li { + margin-top: 1px; +} ul.preview-feature-list { list-style: none; margin:0; @@ -940,6 +950,9 @@ div.checkboxes > label > input { .col-first, .col-second, .col-constructor-name { overflow: auto; } +.col-constructor-name, .method-summary .col-second { + text-indent: 0.5em hanging; +} body:not(.class-declaration-page) .col-first a:link, .col-summary-item-name a:link { font-weight:bold; @@ -957,6 +970,12 @@ div.block { font-size:var(--block-font-size); font-family:var(--block-font-family); line-height:var(--block-line-height); + display: block; + margin:0 10px 5px 0; + color:var(--block-text-color); +} +section.detail div.block { + margin-bottom: 14.4px; } .module-signature, .package-signature, @@ -1006,11 +1025,6 @@ div.block { color:var(--source-linenumber-color, green); padding:0 30px 0 0; } -.block { - display:block; - margin:0 10px 5px 0; - color:var(--block-text-color); -} .deprecated-label, .description-from-type-label, .implementation-label, .member-name-link, .package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label, .restricted-label { @@ -1075,15 +1089,16 @@ input[type="text"] { background-image:var(--glass-svg); background-size:13px; background-repeat:no-repeat; - background-position:3px 4px; + background-position:3px 5px; background-color: var(--search-input-background-color); color: var(--search-input-text-color); - border-color: var(--border-color); + border-style:solid; + border-color: var(--search-border-dark-color) var(--search-border-light-color) var(--search-border-light-color) var(--search-border-dark-color); border-radius: 4px; padding-left:20px; padding-right: 18px; font-size: var(--nav-font-size); - height: 19px; + height: 20px; } input#page-search-input { width: calc(180px + 10vw); @@ -1585,8 +1600,7 @@ button.snippet-copy span { table.borderless, table.plain, table.striped { - margin-top: 10px; - margin-bottom: 10px; + margin: 14px 0; } table.borderless > caption, table.plain > caption, @@ -1780,6 +1794,9 @@ table.striped > tbody > tr > th { main { padding: 10px 12px; } + main [id] { + scroll-margin-top: calc(var(--nav-height) + 10px); + } body { -webkit-text-size-adjust: none; } diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 26c8fb8cd72..cc059a93199 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -1200,16 +1200,22 @@ TEST_VM(os, map_unmap_memory) { TEST_VM(os, map_memory_to_file_aligned) { const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const size_t size = strlen(letters) + 1; + const size_t content_size = strlen(letters) + 1; + const size_t granularity = os::vm_allocation_granularity(); + const size_t alignments[] = { granularity, 2 * granularity, 4 * granularity, 16 * granularity, 1 * M }; int fd = os::open("map_memory_to_file.txt", O_RDWR | O_CREAT, 0666); EXPECT_TRUE(fd > 0); - EXPECT_TRUE(os::write(fd, letters, size)); + ASSERT_TRUE(os::write(fd, letters, content_size)); - char* result = os::map_memory_to_file_aligned(os::vm_allocation_granularity(), os::vm_allocation_granularity(), fd, mtTest); - ASSERT_NOT_NULL(result); - EXPECT_EQ(strcmp(letters, result), 0); - os::unmap_memory(result, os::vm_allocation_granularity()); + const size_t size = granularity; + for (size_t alignment : alignments) { + char* result = os::map_memory_to_file_aligned(size, alignment, fd, mtTest); + ASSERT_NOT_NULL(result) << "Mapping failed for alignment=" << alignment; + EXPECT_TRUE(is_aligned(result, alignment)) << "Failed to aligned to " << alignment; + EXPECT_EQ(strcmp(letters, result), 0) << "Text mismatch at alignment=" << alignment; + os::unmap_memory(result, size); + } ::close(fd); } @@ -1220,3 +1226,36 @@ TEST_VM(os, dll_load_null_error_buf) { void* lib = os::dll_load("NoSuchLib", nullptr, 0); ASSERT_NULL(lib); } + +TEST_VM(os, reserve_memory_aligned_basic) { + const size_t granularity = os::vm_allocation_granularity(); + const size_t alignments[] = { granularity, 2 * granularity, 4 * granularity, 16 * granularity }; + + for (size_t alignment : alignments) { + const size_t size = alignment; + char* result = os::reserve_memory_aligned(size, alignment, mtTest); + ASSERT_NE(result, (char*)nullptr) << "reserve_memory_aligned failed for alignment=" << alignment; + EXPECT_TRUE(is_aligned(result, alignment)) << "Result " << result << " not aligned to " << alignment; + + ASSERT_TRUE(os::commit_memory(result, size, false)); + memset(result, 0xCD, size); + EXPECT_EQ((unsigned char)result[0], 0xCD); + + os::release_memory(result, size); + } +} + +TEST_VM(os, reserve_memory_aligned_large) { + const size_t alignment = 1 * M; + const size_t size = alignment; + + char* result = os::reserve_memory_aligned(size, alignment, mtTest); + ASSERT_NE(result, (char*)nullptr); + EXPECT_TRUE(is_aligned(result, alignment)); + + ASSERT_TRUE(os::commit_memory(result, size, false)); + memset(result, 0xEF, size); + EXPECT_EQ((unsigned char)result[size - 1], 0xEF); + + os::release_memory(result, size); +} diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index f9a4d5ec2a9..c6b00618617 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -33,8 +33,6 @@ vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 lin serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java 8303168 linux-all -serviceability/sa/ClhsdbInspect.java 8283578 windows-x64 - vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8308367 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_a/TestDescription.java 8308367 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_b/TestDescription.java 8308367 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 422e6ddd060..d41f1e3818d 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -103,7 +103,6 @@ runtime/os/TestTracePageSizes.java#compiler-options 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 -runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x runtime/Thread/TestAlwaysPreTouchStacks.java 8383372 macosx-aarch64 @@ -139,6 +138,8 @@ serviceability/sa/ClhsdbThreadContext.java 8356704 windows-x64 serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 +serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java 8385679 generic-all + ############################################################################# # :hotspot_misc diff --git a/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java b/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java index 9e14cd6ea4b..7cc5cda88b6 100644 --- a/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java +++ b/test/hotspot/jtreg/compiler/profiling/TestPrintMethodData.java @@ -64,7 +64,7 @@ public class TestPrintMethodData { private static final Generator GEN_LONG = Generators.G.longs(); private static final int SIZE = 1024; - static void main(String[] args) throws Exception { + public static void main(String[] args) throws Exception { long[] longs = new long[SIZE]; Generators.G.fill(GEN_LONG, longs); diff --git a/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c b/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c index abef2ea050a..4608627688c 100644 --- a/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c +++ b/test/hotspot/jtreg/runtime/StackGuardPages/exeinvoke.c @@ -56,17 +56,13 @@ static jmp_buf context; static volatile int _last_si_code = -1; static volatile int _failures = 0; static volatile int _rec_count = 0; // Number of allocations to hit stack guard page -static volatile int _kp_rec_count = 0; // Kept record of rec_count, for retrying +static volatile int _previous_rec_count = 0; // Kept record of rec_count, for retrying static int _peek_value = 0; // Used for accessing memory to cause SIGSEGV -pid_t gettid() { - return (pid_t) syscall(SYS_gettid); -} - static void handler(int sig, siginfo_t *si, void *unused) { _last_si_code = si->si_code; printf("Got SIGSEGV(%d) at address: 0x%lx\n",si->si_code, (long) si->si_addr); - longjmp(context, 1); + siglongjmp(context, 1); } static char* altstack = NULL; @@ -159,8 +155,16 @@ void *run_java_overflow (void *p) { void do_overflow(){ volatile int *p = NULL; - if (_kp_rec_count == 0 || _rec_count < _kp_rec_count) { - for(;;) { + if (_previous_rec_count == 0) { + // We need to find the appropriate depth to probe into + for (;;) { + _rec_count++; + p = (int*)alloca(128); + _peek_value = p[0]; // Peek + } + } else { + while (_rec_count < _previous_rec_count) { + // This is our second round, we can do exactly 1 less allocation _rec_count++; p = (int*)alloca(128); _peek_value = p[0]; // Peek @@ -168,19 +172,19 @@ void do_overflow(){ } } -void *run_native_overflow(void *p) { +void *run_native_overflow(void *is_other_thread) { // Test that stack guard page is correctly set for initial and non initial thread // and correctly removed for the initial thread volatile int res; - printf("run_native_overflow %ld\n", (long) gettid()); + printf("run_native_overflow, %s", *(int *)is_other_thread ? "in other thread\n" : "in initial thread\n"); call_method_on_jvm("printAlive"); // Initialize statics used in do_overflow - _kp_rec_count = 0; + _previous_rec_count = 0; _rec_count = 0; set_signal_handler(); - if (! setjmp(context)) { + if (! sigsetjmp(context, 1)) { do_overflow(); } @@ -194,7 +198,7 @@ void *run_native_overflow(void *p) { exit(7); } - if (getpid() != gettid()) { + if (*(int *)is_other_thread == 1) { // For non-initial thread we don't unmap the region but call os::uncommit_memory and keep PROT_NONE // so if host has enough swap space we will get the same SEGV with code SEGV_ACCERR(2) trying // to access it as if the guard page is present. @@ -204,11 +208,11 @@ void *run_native_overflow(void *p) { } // Limit depth of recursion for second run. It can't exceed one for first run. - _kp_rec_count = _rec_count; + _previous_rec_count = _rec_count; _rec_count = 0; set_signal_handler(); - if (! setjmp(context)) { + if (!sigsetjmp(context, 1)) { do_overflow(); } @@ -314,8 +318,8 @@ int main (int argc, const char** argv) { if (strcmp(argv[1], "test_native_overflow_initial") == 0) { printf("\nTesting NATIVE_OVERFLOW\n"); printf("Testing stack guard page behaviour for initial thread\n"); - - run_native_overflow(NULL); + int is_other_thread = 0; + run_native_overflow(&is_other_thread); exit((_failures > 0) ? 1 : 0); } @@ -324,11 +328,11 @@ int main (int argc, const char** argv) { init_thread_or_die(&thr, &thread_attr); printf("\nTesting NATIVE_OVERFLOW\n"); printf("Testing stack guard page behaviour for other thread\n"); - - pthread_create(&thr, &thread_attr, run_native_overflow, NULL); + int is_other_thread = 1; + pthread_create(&thr, &thread_attr, run_native_overflow, &is_other_thread); pthread_join(thr, NULL); - - exit((_failures > 0) ? 1 : 0); + // Other-thread test cannot increase _failure count + exit(0); } fprintf(stderr, "Test ERROR. Unknown parameter %s\n", ((argc > 1) ? argv[1] : "none")); diff --git a/test/hotspot/jtreg/runtime/logging/VtablesTest.java b/test/hotspot/jtreg/runtime/logging/VtablesTest.java index a07fe895173..c87c274d31d 100644 --- a/test/hotspot/jtreg/runtime/logging/VtablesTest.java +++ b/test/hotspot/jtreg/runtime/logging/VtablesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ public class VtablesTest { output.shouldContain("NOT overriding with p2.D.nooverride()V"); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1/C"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1.C"); output = new OutputAnalyzer(pb.start()); output.shouldContain("transitive overriding superclass "); output.shouldHaveExitValue(0); diff --git a/test/jdk/java/lang/Thread/virtual/KlassInit.java b/test/jdk/java/lang/Thread/virtual/KlassInit.java index 4f11d667a2b..067d4c5a7f4 100644 --- a/test/jdk/java/lang/Thread/virtual/KlassInit.java +++ b/test/jdk/java/lang/Thread/virtual/KlassInit.java @@ -79,7 +79,10 @@ import java.util.concurrent.CountDownLatch; import java.util.stream.Stream; import java.util.stream.Collectors; +import jdk.test.lib.thread.VThreadRunner; + import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; @@ -96,6 +99,12 @@ class KlassInit { private static final CountDownLatch finishPutStatic = new CountDownLatch(1); private static final CountDownLatch finishFailedInit = new CountDownLatch(1); + @BeforeAll + static void setup() { + // need >=2 carriers for testing pinning + VThreadRunner.ensureParallelism(2); + } + /** * Test that threads blocked waiting for klass to be initialized * on invokestatic bytecode release the carrier. diff --git a/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java b/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java index 875ac5426dd..ce57f654e93 100644 --- a/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java +++ b/test/jdk/java/net/httpclient/access/java.net.http/jdk/internal/net/http/HttpClientImplAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,9 @@ import java.lang.reflect.Field; import java.net.http.HttpClient; import java.util.Objects; import java.util.Set; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Map; public final class HttpClientImplAccess { @@ -64,4 +67,29 @@ public final class HttpClientImplAccess { openedConnections.setAccessible(true); return (Set) openedConnections.get(clientImpl); } + + /** + * Returns all connections in the client's HTTP/2 pool. + */ + public static Collection getHttp2Connections(final HttpClient client) { + Objects.requireNonNull(client, "client"); + final HttpClientImpl clientImpl = impl(client); + if (clientImpl == null) { + throw new IllegalStateException("Unsupported HttpClient implementation"); + } + Http2ClientImpl client2 = clientImpl.client2(); + Map connections = client2.getConnections(); + return connections.values(); + } + + /** + * Returns the cached header encoding buffer for the given Http2Connection. + */ + public static ByteBuffer getCachedHeaderBuffer(final Object conn) { + // The argument to this method is of type Object and not + // Http2Connection because callers outside the module cannot reference + // the package-private Http2Connection class. + Objects.requireNonNull(conn, "conn"); + return ((Http2Connection) conn).getCachedHeaderBuffer(); + } } diff --git a/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java b/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java new file mode 100644 index 00000000000..26fb06ec47d --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/HeaderEncodingBufferReuseTest.java @@ -0,0 +1,139 @@ +/* + * 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. + */ + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.ByteBuffer; +import java.util.Collection; +import javax.net.ssl.SSLContext; +import static java.net.http.HttpClient.Version.HTTP_2; + +import jdk.httpclient.test.lib.common.HttpServerAdapters; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; +import jdk.internal.net.http.HttpClientImplAccess; +import jdk.test.lib.net.URIBuilder; +import jdk.test.lib.net.SimpleSSLContext; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/* + * @test + * @bug 8383248 + * @summary Verifies that Http2Connection.cachedHeaderBuffer is reused + * across multiple requests on the same connection. + * @library /test/lib /test/jdk/java/net/httpclient/lib + * /test/jdk/java/net/httpclient/access + * @build java.net.http/jdk.internal.net.http.HttpClientImplAccess + * jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.net.SimpleSSLContext + * @run junit/othervm + * ${test.main.class} + */ + +public class HeaderEncodingBufferReuseTest implements HttpServerAdapters { + + static String httpUri; + static SSLContext sslContext; + static HttpTestServer testServer; + + @BeforeAll + static void init() throws Exception { + sslContext = SimpleSSLContext.findSSLContext(); + testServer = HttpTestServer.create(HTTP_2, sslContext); + testServer.addHandler(new OkHandler(), "/test"); + testServer.start(); + httpUri = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(testServer.getAddress().getPort()) + .path("/test") + .build() + .toString(); + } + + @AfterAll + static void teardown() { + testServer.stop(); + } + + @Test + void test() throws Exception { + try (HttpClient client = HttpClient.newBuilder() + .proxy(HttpClient.Builder.NO_PROXY) + .version(HttpClient.Version.HTTP_2) + .sslContext(sslContext) + .build()) { + + // Send an initial request to allocate the header encoding buffer. + assertEquals(200, send(client, httpUri, 2).statusCode()); + + Collection connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + Object conn = connections.iterator().next(); + + ByteBuffer cached = HttpClientImplAccess.getCachedHeaderBuffer(conn); + assertNotNull(cached); + + // Send another request and verify the same buffer is reused. + assertEquals(200, send(client, httpUri, 2).statusCode()); + connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + assertSame(conn, connections.iterator().next()); + assertSame(cached, HttpClientImplAccess.getCachedHeaderBuffer(conn)); + + // Verify that the buffer is reused when headers span multiple frames. + assertEquals(200, send(client, httpUri, 300).statusCode()); + connections = HttpClientImplAccess.getHttp2Connections(client); + assertEquals(1, connections.size()); + assertSame(conn, connections.iterator().next()); + assertSame(cached, HttpClientImplAccess.getCachedHeaderBuffer(conn)); + } + } + + static HttpResponse send(HttpClient client, String uri, int headerCount) throws Exception { + HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(uri)) + .POST(BodyPublishers.ofString("test")); + for (int i = 0; i < headerCount; i++) { + builder.header("X-Header-" + i, "value-" + "x".repeat(50) + "-" + i); + } + return client.send(builder.build(), BodyHandlers.discarding()); + } + + static class OkHandler implements HttpTestHandler { + @Override + public void handle(HttpTestExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().close(); + } + } +} diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java index 1500a1b0818..68da9ce5fda 100644 --- a/test/jdk/java/text/Format/ListFormat/TestListFormat.java +++ b/test/jdk/java/text/Format/ListFormat/TestListFormat.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8041488 8316974 8318569 8306116 8385736 + * @bug 8041488 8316974 8318569 8306116 8385736 8385834 * @summary Tests for ListFormat class * @run junit TestListFormat */ @@ -210,6 +210,10 @@ public class TestListFormat { arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE2), arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE3), arguments(CUSTOM_PATTERNS_MINIMAL, SAMPLE4), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE1), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE2), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE3), + arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE4), }; } @@ -237,13 +241,37 @@ public class TestListFormat { }; } - private static Arguments[] getInstance_1Arg_InvalidLongPattern() { + private static final String ZERO_REPEAT = "{0}".repeat(100_000); + private static Arguments[] getInstance_1Arg_InvalidPlaceholder() { return new Arguments[] { - arguments(0, "start pattern is incorrect:"), - arguments(1, "middle pattern is incorrect:"), - arguments(2, "end pattern is incorrect:"), - arguments(3, "pattern for two is incorrect:"), - arguments(4, "pattern for three is incorrect:"), + // Duplicate placeholders + arguments(0, "{0} {0} {1}", "start pattern is incorrect: {0} {0} {1}"), + arguments(0, "{0} {1} {1}", "start pattern is incorrect: {0} {1} {1}"), + arguments(0, "{0} {1} {2}", "start pattern is incorrect: {0} {1} {2}"), + arguments(1, "{0} {0} {1}", "middle pattern is incorrect: {0} {0} {1}"), + arguments(1, "{0} {1} {1}", "middle pattern is incorrect: {0} {1} {1}"), + arguments(1, "{0} {1} {2}", "middle pattern is incorrect: {0} {1} {2}"), + arguments(2, "{0} {0} {1}", "end pattern is incorrect: {0} {0} {1}"), + arguments(2, "{0} {1} {1}", "end pattern is incorrect: {0} {1} {1}"), + arguments(2, "{0} {1} {2}", "end pattern is incorrect: {0} {1} {2}"), + arguments(3, "{0} {0} {1}", "pattern for two is incorrect: {0} {0} {1}"), + arguments(3, "{0} {1} {1}", "pattern for two is incorrect: {0} {1} {1}"), + arguments(3, "{0} {1} {2}", "pattern for two is incorrect: {0} {1} {2}"), + arguments(4, "{0} {2} {1}", "pattern for three is incorrect: {0} {2} {1}"), + arguments(4, "{0} {0} {1} {2}", "pattern for three is incorrect: {0} {0} {1} {2}"), + arguments(4, "{0} {1} {1} {2}", "pattern for three is incorrect: {0} {1} {1} {2}"), + arguments(4, "{0} {1} {2} {2}", "pattern for three is incorrect: {0} {1} {2} {2}"), + arguments(4, ZERO_REPEAT + " {1} {2}", "pattern for three is incorrect: " + ZERO_REPEAT + " {1} {2}"), + + // invalid placeholders + arguments(0, "{0} {1} {", "start pattern is incorrect: {0} {1} {"), + arguments(0, "{0} {1} }", "start pattern is incorrect: {0} {1} }"), + arguments(3, "{0} {1} {3}", "pattern for two is incorrect: {0} {1} {3}"), + arguments(4, "{3} {0} {1}", "pattern for three is incorrect: {3} {0} {1}"), + arguments(4, "{333} {0} {1}", "pattern for three is incorrect: {333} {0} {1}"), + arguments(4, "{0} {1} {abc}", "pattern for three is incorrect: {0} {1} {abc}"), + arguments(4, "{0} {1} {2, number}", "pattern for three is incorrect: {0} {1} {2, number}"), + arguments(4, "{0} {1} {2} {3}", "pattern for three is incorrect: {0} {1} {2} {3}"), }; } @@ -264,7 +292,7 @@ public class TestListFormat { @ParameterizedTest @MethodSource - void getInstance_1Arg_InvalidLongPattern(int index, String expected) { + void getInstance_1Arg_InvalidPlaceholder(int index, String invalidPattern, String expected) { var patterns = new String[]{ "{0}, {1}", "{0}, {1}", @@ -272,13 +300,12 @@ public class TestListFormat { "{0} and {1}", "{0} {1} {2}" }; - patterns[index] = "{0}".repeat(100_000); + patterns[index] = invalidPattern; - // Ensures validation of invalid long patterns completes without timing out var msg = assertThrows(IllegalArgumentException.class, () -> ListFormat.getInstance(patterns)) .getMessage(); - assertEquals(expected, msg.substring(0, Math.min(msg.length(), expected.length()))); + assertEquals(expected, msg); } @ParameterizedTest diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java index de1caaab2d9..85d7921f2ed 100644 --- a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java @@ -663,6 +663,23 @@ public class ForkJoinPoolTest extends JSR166TestCase { } } + public void testCallerInterruptedDuringSubmit() throws InterruptedException, ExecutionException { + final Thread submitter = Thread.currentThread(); + final ExecutorService p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int i = 0; i < 512; ++i) { // Enough repetitions such that any race condition is bound to materialize + try { + p.submit(submitter::interrupt).get(); + // If we don't get an InterruptedException, then the current thread should be interrupted + assertTrue(Thread.interrupted()); + } catch (InterruptedException e) { + // If we do get an InterruptedException, then the current thread should not be interrupted + assertTrue(!Thread.interrupted()); + } + } + } + } + /** * get of submit(callable) throws ExecutionException if callable * throws exception diff --git a/test/jdk/javax/accessibility/awt/CheckboxTest.java b/test/jdk/javax/accessibility/awt/CheckboxTest.java new file mode 100644 index 00000000000..7c690c16848 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/CheckboxTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Checkbox Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main CheckboxTest + */ + +import java.awt.AWTException; +import java.awt.Checkbox; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class CheckboxTest { + + private static Checkbox checkbox; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Checkbox Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Checkbox"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + CheckboxTest checkboxTest = new CheckboxTest(); + EventQueue.invokeAndWait(checkboxTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(checkboxTest::test); + } finally { + checkboxTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Checkbox Test"); + checkbox = new Checkbox("This is a checkbox", true); + + checkbox.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + checkbox.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(checkbox); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyCheckboxAccessibility( + checkbox, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new CheckboxStateTester( + checkbox, + checkbox.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + checkbox.setState(!checkbox.getState()); + + AccessibleTestUtils.verifyCheckboxAccessibility( + checkbox, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new CheckboxStateTester( + checkbox, + checkbox.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class CheckboxStateTester + extends AccessibleStateSetTester { + private final Checkbox checkbox; + private final AccessibleStateSet set; + + private CheckboxStateTester(Checkbox checkbox, AccessibleStateSet set) { + super(checkbox, set); + this.checkbox = checkbox; + this.set = set; + } + + @Override + public void testChecked() { + if (set.contains(AccessibleState.CHECKED)) { + if (!checkbox.getState()) { + throw new RuntimeException( + "AccessibleStateSet contains CHECKED but " + + "this component is not checked"); + } + } else { + if (checkbox.getState()) { + throw new RuntimeException( + "AccessibleStateSet does not contain CHECKED " + + "but this component is checked"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/FrameTest.java b/test/jdk/javax/accessibility/awt/FrameTest.java new file mode 100644 index 00000000000..4abe3246574 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/FrameTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Frame Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main FrameTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class FrameTest { + + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Frame Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Frame"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + FrameTest frameTest = new FrameTest(); + EventQueue.invokeAndWait(frameTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(frameTest::test); + } finally { + frameTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Frame Test"); + + frame.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + frame.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyFrameAccessibility( + frame, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new FrameStateTester( + frame, + frame.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + frame.setResizable(false); + + AccessibleTestUtils.verifyFrameAccessibility( + frame, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new FrameStateTester( + frame, + frame.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class FrameStateTester + extends AccessibleStateSetTester { + private final Frame component; + private final AccessibleStateSet set; + + private FrameStateTester(Frame frame, AccessibleStateSet set) { + super(frame, set); + this.component = frame; + this.set = set; + } + + @Override + public void testResizable() { + if (set.contains(AccessibleState.RESIZABLE)) { + if (!component.isResizable()) { + throw new RuntimeException( + "AccessibleStateSet contains RESIZABLE but " + + "this component is not resizable"); + } + } else { + if (component.isResizable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain RESIZABLE " + + "but this component is resizable"); + } + } + } + + @Override + public void testActive() { + if (set.contains(AccessibleState.ACTIVE)) { + if (component.getFocusOwner() == null) { + throw new RuntimeException( + "AccessibleStateSet contains ACTIVE but " + + "this component is not active"); + } + } else { + if (component.getFocusOwner() != null) { + throw new RuntimeException( + "AccessibleStateSet does not contain ACTIVE but " + + "this component is active"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/LabelTest.java b/test/jdk/javax/accessibility/awt/LabelTest.java new file mode 100644 index 00000000000..dd837793eb5 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/LabelTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Label Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main LabelTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class LabelTest { + + private static Label label; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Label Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Label"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + LabelTest labelTest = new LabelTest(); + EventQueue.invokeAndWait(labelTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(labelTest::test); + } finally { + labelTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Label Test"); + label = new Label("This is a label"); + + label.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + label.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(label); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyLabelAccessibility( + label, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + label, + label.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/ListTest.java b/test/jdk/javax/accessibility/awt/ListTest.java new file mode 100644 index 00000000000..011d850a4cb --- /dev/null +++ b/test/jdk/javax/accessibility/awt/ListTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary List Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main ListTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class ListTest { + + private static List list; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "List Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, List"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + ListTest listTest = new ListTest(); + EventQueue.invokeAndWait(listTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(listTest::test); + } finally { + listTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("List Test"); + list = new List(); + + list.add("Mercury"); + list.add("Venus"); + list.add("Earth"); + list.add("JavaSoft"); + list.add("Mars"); + list.add("Jupiter"); + list.add("Saturn"); + list.add("Uranus"); + list.add("Neptune"); + list.add("Pluto"); + + list.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + list.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(list); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyListAccessibility( + list, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new ListStateTester( + list, + list.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + list.setMultipleMode(!list.isMultipleMode()); + + AccessibleTestUtils.verifyListAccessibility( + list, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new ListStateTester( + list, + list.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class ListStateTester + extends AccessibleStateSetTester { + private final List list; + private final AccessibleStateSet set; + + private ListStateTester(List list, AccessibleStateSet set) { + super(list, set); + this.list = list; + this.set = set; + } + + @Override + public void testMultiSelectable() { + if (set.contains(AccessibleState.MULTISELECTABLE)) { + if (!list.isMultipleMode()) { + throw new RuntimeException( + "AccessibleStateSet contains MULTISELECTABLE " + + "but this component is not multiselectable"); + } + } else { + if (list.isMultipleMode()) { + throw new RuntimeException( + "AccessibleStateSet does not contain " + + "MULTISELECTABLE but this component is " + + "multiselectable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuBarTest.java b/test/jdk/javax/accessibility/awt/MenuBarTest.java new file mode 100644 index 00000000000..83445fde61b --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuBarTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary MenuBar Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuBarTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuBarTest { + + private static MenuBar menuBar; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Menu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, MenuBar"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuBarTest menuBarTest = new MenuBarTest(); + EventQueue.invokeAndWait(menuBarTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuBarTest::test); + } finally { + menuBarTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("MenuBar Test"); + menuBar = new MenuBar(); + + Menu menu = new Menu("Menu 1"); + menu.add(new MenuItem("One")); + menu.add(new MenuItem("Two")); + menuBar.add(menu); + + menuBar.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menuBar.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuBarAccessibility( + menuBar, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuItemTest.java b/test/jdk/javax/accessibility/awt/MenuItemTest.java new file mode 100644 index 00000000000..0cfe342e843 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuItemTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary MenuItem Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuItemTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuItemTest { + + private static MenuItem menuItem; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "MenuItem Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, MenuItem"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuItemTest menuItemTest = new MenuItemTest(); + EventQueue.invokeAndWait(menuItemTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuItemTest::test); + } finally { + menuItemTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("MenuItem Test"); + + MenuBar menuBar = new MenuBar(); + Menu menu = new Menu("Menu"); + menuItem = new MenuItem("This here's a MenuItem"); + + menu.add(menuItem); + menuBar.add(menu); + + menuItem.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menuItem.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuItemAccessibility( + menuItem, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/MenuTest.java b/test/jdk/javax/accessibility/awt/MenuTest.java new file mode 100644 index 00000000000..15c51ca4214 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/MenuTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Menu Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main MenuTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MenuTest { + + private static Menu menu; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Menu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Menu"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MenuTest menuTest = new MenuTest(); + EventQueue.invokeAndWait(menuTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(menuTest::test); + } finally { + menuTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Menu Test"); + + MenuBar menuBar = new MenuBar(); + menu = new Menu("File"); + menuBar.add(menu); + + menu.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + menu.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.setMenuBar(menuBar); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyMenuAccessibility( + menu, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/PanelTest.java b/test/jdk/javax/accessibility/awt/PanelTest.java new file mode 100644 index 00000000000..abfacc7485b --- /dev/null +++ b/test/jdk/javax/accessibility/awt/PanelTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Panel Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main PanelTest + */ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class PanelTest { + + private static Panel panel; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "Panel Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Panel"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + PanelTest panelTest = new PanelTest(); + EventQueue.invokeAndWait(panelTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(panelTest::test); + } finally { + panelTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("Panel Test"); + panel = new Panel(); + + for (int i = 0; i < 5; i++) { + panel.add(new Button("Button #" + i)); + } + + panel.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + panel.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyPanelAccessibility( + panel, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + panel, + panel.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/PopupMenuTest.java b/test/jdk/javax/accessibility/awt/PopupMenuTest.java new file mode 100644 index 00000000000..8d329a92322 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/PopupMenuTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary PopupMenu Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleMenuComponentTester + * @run main PopupMenuTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.PopupMenu; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class PopupMenuTest { + + private static PopupMenu popupMenu; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "PopupMenu Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, PopupMenu"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + PopupMenuTest popupMenuTest = new PopupMenuTest(); + EventQueue.invokeAndWait(popupMenuTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(popupMenuTest::test); + } finally { + popupMenuTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("PopupMenu Test"); + popupMenu = new PopupMenu("PopupMenu"); + + popupMenu.add("Sleepy"); + popupMenu.add("Happy"); + popupMenu.add("Grumpy"); + popupMenu.add("Dopey"); + + popupMenu.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + popupMenu.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(popupMenu); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyPopupMenuAccessibility( + popupMenu, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + } +} diff --git a/test/jdk/javax/accessibility/awt/ScrollPaneTest.java b/test/jdk/javax/accessibility/awt/ScrollPaneTest.java new file mode 100644 index 00000000000..7f706647482 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/ScrollPaneTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary ScrollPane Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main ScrollPaneTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.lang.reflect.InvocationTargetException; + +public class ScrollPaneTest { + + private static ScrollPane scrollPane; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "ScrollPane Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, ScrollPane"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + ScrollPaneTest scrollPaneTest = new ScrollPaneTest(); + EventQueue.invokeAndWait(scrollPaneTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(scrollPaneTest::test); + } finally { + scrollPaneTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("ScrollPane Test"); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + + scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + scrollPane.setSize(frame.getSize().width, frame.getSize().height); + scrollPane.add(new Label("This is a label with quite a bit of text.")); + + scrollPane.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + scrollPane.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(scrollPane); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyScrollPaneAccessibility( + scrollPane, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new AccessibleStateSetTester( + scrollPane, + scrollPane.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } +} diff --git a/test/jdk/javax/accessibility/awt/TextAreaTest.java b/test/jdk/javax/accessibility/awt/TextAreaTest.java new file mode 100644 index 00000000000..388a22324f9 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/TextAreaTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary TextArea Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main TextAreaTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextArea; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class TextAreaTest { + + private static TextArea textArea; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "TextArea Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, TextArea"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TextAreaTest textAreaTest = new TextAreaTest(); + EventQueue.invokeAndWait(textAreaTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(textAreaTest::test); + } finally { + textAreaTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("TextAreaTest"); + String TEXT_CONTENT = """ + 1. Test TextArea javax.accessibility methods + 2. Test TextArea javax.accessibility setAccessibleName + 3. Test TextArea javax.accessibility setAccessibleDescription + 4. Test TextArea javax.accessibility setAccessibleStateSet + """; + textArea = new TextArea(TEXT_CONTENT, 24, 80); + + textArea.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + textArea.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(textArea); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyTextAreaAccessibility( + textArea, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textArea, + textArea.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + textArea.setEditable(false); + + AccessibleTestUtils.verifyTextAreaAccessibility( + textArea, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textArea, + textArea.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class TextStateTester + extends AccessibleStateSetTester { + private final TextArea textArea; + private final AccessibleStateSet stateSet; + + private TextStateTester(TextArea textArea, + AccessibleStateSet stateSet) { + super(textArea, stateSet); + this.textArea = textArea; + this.stateSet = stateSet; + } + + @Override + public void testEditable() { + if (stateSet.contains(AccessibleState.EDITABLE)) { + if (!textArea.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet contains EDITABLE but " + + "this component is not editable"); + } + } else { + if (textArea.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain EDITABLE " + + "but this component is editable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/TextFieldTest.java b/test/jdk/javax/accessibility/awt/TextFieldTest.java new file mode 100644 index 00000000000..96deaf3b7bc --- /dev/null +++ b/test/jdk/javax/accessibility/awt/TextFieldTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary TextField Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main TextFieldTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class TextFieldTest { + + private static TextField textField; + private static Frame frame; + + private static final String ACCESSIBLE_NAME = "TextField Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, TextField"; + private static final String TEXT = + "I love Cheesy Poofs you love Cheesy Poofs if we didn't " + + "eat Cheesy Poofs we'd be lame!"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TextFieldTest textFieldTest = new TextFieldTest(); + EventQueue.invokeAndWait(textFieldTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(textFieldTest::test); + } finally { + textFieldTest.dispose(); + } + } + + private void createGUI() { + frame = new Frame("TextField Test"); + textField = new TextField(TEXT, 80); + + textField.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + textField.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + frame.add(textField); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyTextFieldAccessibility( + textField, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textField, + textField.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + + textField.setEditable(false); + + AccessibleTestUtils.verifyTextFieldAccessibility( + textField, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new TextStateTester( + textField, + textField.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class TextStateTester + extends AccessibleStateSetTester { + private final TextField textField; + private final AccessibleStateSet set; + + private TextStateTester(TextField textField, AccessibleStateSet set) { + super(textField, set); + this.textField = textField; + this.set = set; + } + + @Override + public void testEditable() { + if (set.contains(AccessibleState.EDITABLE)) { + if (!textField.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet contains EDITABLE but " + + "this component is not editable"); + } + } else { + if (textField.isEditable()) { + throw new RuntimeException( + "AccessibleStateSet does not contain EDITABLE " + + "but this component is editable"); + } + } + } + } +} diff --git a/test/jdk/javax/accessibility/awt/WindowTest.java b/test/jdk/javax/accessibility/awt/WindowTest.java new file mode 100644 index 00000000000..dc70ce75d90 --- /dev/null +++ b/test/jdk/javax/accessibility/awt/WindowTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @summary Window Accessibility test. + * @library ../../swing/regtesthelpers/accessibility/ + * @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester + * @run main WindowTest + */ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +public class WindowTest { + + private static Window window; + + private static final String ACCESSIBLE_NAME = "Window Test"; + private static final String ACCESSIBLE_DESCRIPTION = + "Regression Test: javax.accessibility, Window"; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + WindowTest windowTest = new WindowTest(); + EventQueue.invokeAndWait(windowTest::createGUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(5000); + + try { + EventQueue.invokeAndWait(windowTest::test); + } finally { + windowTest.dispose(); + } + } + + private void createGUI() { + window = new Window(new Frame("Frame")); + window.setSize(300, 300); + window.setLocationRelativeTo(null); + + window.getAccessibleContext().setAccessibleName(ACCESSIBLE_NAME); + window.getAccessibleContext().setAccessibleDescription( + ACCESSIBLE_DESCRIPTION); + + window.setVisible(true); + } + + private void dispose() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (window != null) { + window.dispose(); + } + }); + } + + private void test() { + AccessibleTestUtils.verifyWindowAccessibility( + window, + ACCESSIBLE_NAME, + ACCESSIBLE_DESCRIPTION + ); + + new WindowStateTester( + window, + window.getAccessibleContext().getAccessibleStateSet() + ).testAll(); + } + + private static final class WindowStateTester + extends AccessibleStateSetTester { + private final Window window; + private final AccessibleStateSet set; + + private WindowStateTester(Window window, AccessibleStateSet set) { + super(window, set); + this.window = window; + this.set = set; + } + + @Override + public void testActive() { + if (set.contains(AccessibleState.ACTIVE)) { + if (window.getFocusOwner() == null) { + throw new RuntimeException( + "AccessibleStateSet contains ACTIVE but " + + "this component is not active"); + } + } else { + if (window.getFocusOwner() != null) { + throw new RuntimeException( + "AccessibleStateSet does not contain ACTIVE " + + "but this component is active"); + } + } + } + } +} diff --git a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java new file mode 100644 index 00000000000..21b91aafbcd --- /dev/null +++ b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleMenuComponentTester.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Font; +import java.awt.MenuComponent; + +import javax.accessibility.AccessibleComponent; + +public class AccessibleMenuComponentTester { + + private final AccessibleComponent acomp; + private final MenuComponent comp; + + public AccessibleMenuComponentTester(MenuComponent menuComponent, + AccessibleComponent ac) { + if (menuComponent == null) { + throw new RuntimeException("MenuComponent should not be null"); + } + + if (ac == null) { + throw new RuntimeException("AccessibleComponent should not be null"); + } + + this.comp = menuComponent; + this.acomp = ac; + } + + // The only method supported by MenuComponents is getFont(). Everything + // else should return null. + public void test() { + testGetBackground(); + testGetBounds(); + testGetCursor(); + testGetFont(); + testGetForeground(); + testGetLocation(); + testGetLocationOnScreen(); + testGetSize(); + testIsEnabled(); + testIsFocusTraversable(); + testIsShowing(); + testIsVisible(); + } + + public void testGetBackground() { + } + + public void testGetBounds() { + } + + public void testGetCursor() { + } + + public void testGetFont() { + Font accessibleFont = acomp.getFont(); + Font componentFont = comp.getFont(); + + if (componentFont == null) { + if (accessibleFont != null) { + throw new RuntimeException( + "MenuComponent.getFont returned null but " + + "AccessibleComponent.getFont did not"); + } + } else if (!componentFont.equals(accessibleFont)) { + throw new RuntimeException( + "AccessibleComponent.getFont does not match " + + "MenuComponent.getFont"); + } + } + + public void testGetForeground() { + } + + public void testGetLocation() { + } + + public void testGetLocationOnScreen() { + } + + public void testGetSize() { + } + + public void testIsEnabled() { + } + + public void testIsFocusTraversable() { + } + + public void testIsShowing() { + } + + public void testIsVisible() { + } +} diff --git a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java index 2410cff997a..9de4a8d8089 100644 --- a/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java +++ b/test/jdk/javax/swing/regtesthelpers/accessibility/AccessibleTestUtils.java @@ -22,17 +22,33 @@ */ import java.awt.Button; +import java.awt.Checkbox; import java.awt.Choice; import java.awt.Component; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.MenuItem; +import java.awt.Panel; +import java.awt.PopupMenu; import java.awt.Scrollbar; +import java.awt.ScrollPane; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.Window; import java.util.Locale; import java.util.Objects; +import javax.accessibility.Accessible; import javax.accessibility.AccessibleAction; import javax.accessibility.AccessibleComponent; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleText; import javax.accessibility.AccessibleValue; @@ -51,32 +67,22 @@ public final class AccessibleTestUtils { boolean expectSelection, boolean expectText, boolean expectValue) { - Objects.requireNonNull(context, "AccessibleContext must not be null"); - assertExpectedString( - "getAccessibleName", - expectedName, - context.getAccessibleName() - ); + assertExpectedString("getAccessibleName", + expectedName, context.getAccessibleName()); + assertExpectedString("getAccessibleDescription", + expectedDescription, context.getAccessibleDescription()); - assertExpectedString( - "getAccessibleDescription", - expectedDescription, - context.getAccessibleDescription() - ); + AccessibleRole actualRole = context.getAccessibleRole(); + if (actualRole == null) { + throw new RuntimeException("getAccessibleRole returned null"); + } - if (expectedRole != null) { - AccessibleRole actualRole = context.getAccessibleRole(); - if (actualRole == null) { - throw new RuntimeException("getAccessibleRole returned null"); - } - if (!expectedRole.equals(actualRole)) { - throw new RuntimeException(String.format( - "getAccessibleRole returned [%s]; expected [%s]", - actualRole, expectedRole - )); - } + if (!expectedRole.equals(actualRole)) { + throw new RuntimeException( + "getAccessibleRole returned [" + actualRole + + "]; expected [" + expectedRole + "]"); } AccessibleStateSet stateSet = context.getAccessibleStateSet(); @@ -84,10 +90,14 @@ public final class AccessibleTestUtils { throw new RuntimeException("getAccessibleStateSet returned null"); } - assertPresence("getAccessibleAction", expectAction, context.getAccessibleAction()); - assertPresence("getAccessibleSelection", expectSelection, context.getAccessibleSelection()); - assertPresence("getAccessibleText", expectText, context.getAccessibleText()); - assertPresence("getAccessibleValue", expectValue, context.getAccessibleValue()); + assertPresence("getAccessibleAction", + expectAction, context.getAccessibleAction()); + assertPresence("getAccessibleSelection", + expectSelection, context.getAccessibleSelection()); + assertPresence("getAccessibleText", + expectText, context.getAccessibleText()); + assertPresence("getAccessibleValue", + expectValue, context.getAccessibleValue()); } public static void verifyAWTComponentAccessibility( @@ -99,10 +109,13 @@ public final class AccessibleTestUtils { boolean expectSelection, boolean expectText, boolean expectValue) { - - Objects.requireNonNull(component, "Component under test must not be null"); + Objects.requireNonNull(component, "Component must not be null"); AccessibleContext context = component.getAccessibleContext(); + if (context == null) { + throw new RuntimeException("getAccessibleContext returned null"); + } + verifyAccessibleContextCommon( context, expectedName, @@ -111,12 +124,12 @@ public final class AccessibleTestUtils { expectAction, expectSelection, expectText, - expectValue - ); + expectValue); assertLocaleMatches(component, context); - AccessibleComponent accessibleComponent = context.getAccessibleComponent(); + AccessibleComponent accessibleComponent = + context.getAccessibleComponent(); if (accessibleComponent == null) { throw new RuntimeException("getAccessibleComponent returned null"); } @@ -124,101 +137,10 @@ public final class AccessibleTestUtils { new AccessibleComponentTester(component, accessibleComponent).test(); } - public static void verifyChoiceAccessibility( - Choice choice, - String expectedName, - String expectedDescription) { - - Objects.requireNonNull(choice, "Choice must not be null"); - - verifyAWTComponentAccessibility( - choice, - expectedName, - expectedDescription, - AccessibleRole.COMBO_BOX, - true, - false, - false, - false - ); - - AccessibleContext context = choice.getAccessibleContext(); - - AccessibleAction action = context.getAccessibleAction(); - if (action == null) { - throw new RuntimeException("getAccessibleAction should not return null for Choice"); - } - - AccessibleValue value = context.getAccessibleValue(); - if (value != null) { - throw new RuntimeException("getAccessibleValue should return null for Choice"); - } - } - - public static void verifyScrollbarAccessibility( - Scrollbar scrollbar, - String expectedName, - String expectedDescription) { - - Objects.requireNonNull(scrollbar, "Scrollbar must not be null"); - - verifyAWTComponentAccessibility( - scrollbar, - expectedName, - expectedDescription, - AccessibleRole.SCROLL_BAR, - false, - false, - false, - true - ); - - AccessibleValue value = scrollbar.getAccessibleContext().getAccessibleValue(); - if (value == null) { - throw new RuntimeException("getAccessibleValue should not return null for Scrollbar"); - } - - assertIntValueEquals( - "getCurrentAccessibleValue", - scrollbar.getValue(), - value.getCurrentAccessibleValue() - ); - - assertIntValueEquals( - "getMinimumAccessibleValue", - scrollbar.getMinimum(), - value.getMinimumAccessibleValue() - ); - - assertIntValueEquals( - "getMaximumAccessibleValue", - scrollbar.getMaximum(), - value.getMaximumAccessibleValue() - ); - - if (!value.setCurrentAccessibleValue(Integer.valueOf(5))) { - throw new RuntimeException("setCurrentAccessibleValue(5) returned false for Scrollbar"); - } - - assertIntValueEquals( - "getCurrentAccessibleValue after setCurrentAccessibleValue(5)", - 5, - value.getCurrentAccessibleValue() - ); - - if (scrollbar.getValue() != 5) { - throw new RuntimeException( - "setCurrentAccessibleValue(5) did not update Scrollbar.getValue(); actual value: " - + scrollbar.getValue() - ); - } - } - public static void verifyButtonAccessibility( Button button, String expectedName, String expectedDescription) { - Objects.requireNonNull(button, "Button must not be null"); verifyAWTComponentAccessibility( @@ -229,106 +151,576 @@ public final class AccessibleTestUtils { true, false, false, - true - ); + true); AccessibleContext context = button.getAccessibleContext(); + verifyClickAction(context, "Button"); + verifyZeroAccessibleValue(context, "Button"); + } + public static void verifyCheckboxAccessibility( + Checkbox checkbox, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(checkbox, "Checkbox must not be null"); + + verifyAWTComponentAccessibility( + checkbox, + expectedName, + expectedDescription, + AccessibleRole.CHECK_BOX, + true, + false, + false, + true); + } + + public static void verifyChoiceAccessibility( + Choice choice, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(choice, "Choice must not be null"); + + verifyAWTComponentAccessibility( + choice, + expectedName, + expectedDescription, + AccessibleRole.COMBO_BOX, + true, + false, + false, + false); + } + + public static void verifyFrameAccessibility( + Frame frame, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(frame, "Frame must not be null"); + + verifyAWTComponentAccessibility( + frame, + expectedName, + expectedDescription, + AccessibleRole.FRAME, + false, + false, + false, + false); + } + + public static void verifyLabelAccessibility( + Label label, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(label, "Label must not be null"); + + verifyAWTComponentAccessibility( + label, + expectedName, + expectedDescription, + AccessibleRole.LABEL, + false, + false, + false, + false); + } + + public static void verifyListAccessibility( + List list, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(list, "List must not be null"); + + verifyAWTComponentAccessibility( + list, + expectedName, + expectedDescription, + AccessibleRole.LIST, + false, + true, + false, + false); + + verifyListChildren(list); + } + + public static void verifyPanelAccessibility( + Panel panel, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(panel, "Panel must not be null"); + + verifyAWTComponentAccessibility( + panel, + expectedName, + expectedDescription, + AccessibleRole.PANEL, + false, + false, + false, + false); + + verifyContainerChildren(panel, "Panel"); + } + + public static void verifyScrollbarAccessibility( + Scrollbar scrollbar, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(scrollbar, "Scrollbar must not be null"); + + verifyAWTComponentAccessibility( + scrollbar, + expectedName, + expectedDescription, + AccessibleRole.SCROLL_BAR, + false, + false, + false, + true); + + AccessibleValue value = + scrollbar.getAccessibleContext().getAccessibleValue(); + + assertIntValueEquals( + "getCurrentAccessibleValue", + scrollbar.getValue(), + value.getCurrentAccessibleValue()); + + assertIntValueEquals( + "getMinimumAccessibleValue", + scrollbar.getMinimum(), + value.getMinimumAccessibleValue()); + + assertIntValueEquals( + "getMaximumAccessibleValue", + scrollbar.getMaximum(), + value.getMaximumAccessibleValue()); + + if (!value.setCurrentAccessibleValue(Integer.valueOf(5))) { + throw new RuntimeException( + "setCurrentAccessibleValue should not return false " + + "for Scrollbar"); + } + + assertIntValueEquals( + "getCurrentAccessibleValue after setCurrentAccessibleValue(5)", + 5, + value.getCurrentAccessibleValue()); + + if (scrollbar.getValue() != 5) { + throw new RuntimeException( + "setCurrentAccessibleValue should change the Scrollbar " + + "value"); + } + } + + public static void verifyScrollPaneAccessibility( + ScrollPane scrollPane, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(scrollPane, "ScrollPane must not be null"); + + verifyAWTComponentAccessibility( + scrollPane, + expectedName, + expectedDescription, + AccessibleRole.SCROLL_PANE, + false, + false, + false, + false); + } + + public static void verifyTextAreaAccessibility( + TextArea textArea, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(textArea, "TextArea must not be null"); + + verifyAWTComponentAccessibility( + textArea, + expectedName, + expectedDescription, + AccessibleRole.TEXT, + false, + false, + true, + false); + } + + public static void verifyTextFieldAccessibility( + TextField textField, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(textField, "TextField must not be null"); + + verifyAWTComponentAccessibility( + textField, + expectedName, + expectedDescription, + AccessibleRole.TEXT, + false, + false, + true, + false); + } + + public static void verifyWindowAccessibility( + Window window, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(window, "Window must not be null"); + + verifyAWTComponentAccessibility( + window, + expectedName, + expectedDescription, + AccessibleRole.WINDOW, + false, + false, + false, + false); + } + + public static void verifyMenuAccessibility( + Menu menu, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menu, "Menu must not be null"); + + verifyMenuComponentAccessibility( + menu, + expectedName, + expectedDescription, + AccessibleRole.MENU, + true, + true, + false, + true, + "Menu"); + + AccessibleContext context = menu.getAccessibleContext(); + verifyClickAction(context, "Menu"); + verifyZeroAccessibleValue(context, "Menu"); + } + + public static void verifyMenuBarAccessibility( + MenuBar menuBar, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menuBar, "MenuBar must not be null"); + + verifyMenuComponentAccessibility( + menuBar, + expectedName, + expectedDescription, + AccessibleRole.MENU_BAR, + false, + true, + false, + false, + "MenuBar"); + } + + public static void verifyMenuItemAccessibility( + MenuItem menuItem, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(menuItem, "MenuItem must not be null"); + + verifyMenuComponentAccessibility( + menuItem, + expectedName, + expectedDescription, + AccessibleRole.MENU_ITEM, + true, + true, + false, + true, + "MenuItem"); + + AccessibleContext context = menuItem.getAccessibleContext(); + verifyClickAction(context, "MenuItem"); + verifyZeroAccessibleValue(context, "MenuItem"); + } + + public static void verifyPopupMenuAccessibility( + PopupMenu popupMenu, + String expectedName, + String expectedDescription) { + Objects.requireNonNull(popupMenu, "PopupMenu must not be null"); + + verifyMenuComponentAccessibility( + popupMenu, + expectedName, + expectedDescription, + AccessibleRole.POPUP_MENU, + true, + true, + false, + true, + "PopupMenu"); + + AccessibleContext context = popupMenu.getAccessibleContext(); + verifyClickAction(context, "PopupMenu"); + verifyZeroAccessibleValue(context, "PopupMenu"); + } + + private static void verifyMenuComponentAccessibility( + MenuComponent menuComponent, + String expectedName, + String expectedDescription, + AccessibleRole expectedRole, + boolean expectAction, + boolean expectSelection, + boolean expectText, + boolean expectValue, + String componentName) { + Objects.requireNonNull(menuComponent, + componentName + " must not be null"); + + AccessibleContext context = menuComponent.getAccessibleContext(); + if (context == null) { + throw new RuntimeException("getAccessibleContext returned null"); + } + + verifyAccessibleContextCommon( + context, + expectedName, + expectedDescription, + expectedRole, + expectAction, + expectSelection, + expectText, + expectValue); + + AccessibleComponent accessibleComponent = + context.getAccessibleComponent(); + if (accessibleComponent == null) { + throw new RuntimeException("getAccessibleComponent returned null"); + } + + new AccessibleMenuComponentTester( + menuComponent, accessibleComponent).test(); + } + + private static void verifyClickAction(AccessibleContext context, + String componentName) { AccessibleAction action = context.getAccessibleAction(); if (action == null) { - throw new RuntimeException("getAccessibleAction should not return null for Button"); + throw new RuntimeException( + "getAccessibleAction should not return null for " + + componentName); } int actionCount = action.getAccessibleActionCount(); if (actionCount != 1) { throw new RuntimeException( - "getAccessibleActionCount should return 1 for Button; got " + actionCount - ); + "getAccessibleActionCount returned the wrong number for " + + componentName); } String actionDescription = action.getAccessibleActionDescription(0); if (!"click".equals(actionDescription)) { throw new RuntimeException( - "getAccessibleActionDescription(0) should return \"click\" for Button; got [" - + actionDescription + "]" - ); + "getAccessibleActionDescription returned the wrong " + + "description for " + componentName); } + } + private static void verifyZeroAccessibleValue(AccessibleContext context, + String componentName) { AccessibleValue value = context.getAccessibleValue(); if (value == null) { - throw new RuntimeException("getAccessibleValue should not return null for Button"); + throw new RuntimeException( + "getAccessibleValue should not return null for " + + componentName); } - assertIntValueEquals("getCurrentAccessibleValue", 0, value.getCurrentAccessibleValue()); - assertIntValueEquals("getMinimumAccessibleValue", 0, value.getMinimumAccessibleValue()); - assertIntValueEquals("getMaximumAccessibleValue", 0, value.getMaximumAccessibleValue()); + assertIntValueEquals( + "getCurrentAccessibleValue", + 0, + value.getCurrentAccessibleValue()); + + assertIntValueEquals( + "getMinimumAccessibleValue", + 0, + value.getMinimumAccessibleValue()); + + assertIntValueEquals( + "getMaximumAccessibleValue", + 0, + value.getMaximumAccessibleValue()); if (value.setCurrentAccessibleValue(Integer.valueOf(5))) { throw new RuntimeException( - "setCurrentAccessibleValue(5) should return false for Button" - ); + "setCurrentAccessibleValue should return false for " + + componentName); } assertIntValueEquals( "getCurrentAccessibleValue after setCurrentAccessibleValue(5)", 0, - value.getCurrentAccessibleValue() - ); + value.getCurrentAccessibleValue()); } - private static void assertExpectedString(String methodName, String expected, String actual) { + private static void verifyListChildren(List list) { + AccessibleContext context = list.getAccessibleContext(); + + int childCount = context.getAccessibleChildrenCount(); + if (childCount != list.getItemCount()) { + throw new RuntimeException( + "getAccessibleChildrenCount returned an incorrect value " + + "for List"); + } + + for (int i = 0; i < childCount; i++) { + Accessible child = context.getAccessibleChild(i); + if (child == null) { + throw new RuntimeException( + "getAccessibleChild returned null for child " + i); + } + + AccessibleContext childContext = child.getAccessibleContext(); + if (childContext == null) { + throw new RuntimeException( + "getAccessibleContext returned null for List child " + + i); + } + + if (childContext.getAccessibleRole() != AccessibleRole.LIST_ITEM) { + throw new RuntimeException( + "The AccessibleRole of AccessibleAWTListChild is " + + "incorrect for child " + i); + } + + if (childContext.getAccessibleIndexInParent() != i) { + throw new RuntimeException( + "getAccessibleIndexInParent returned an incorrect " + + "value for AccessibleAWTListChild " + i); + } + + AccessibleStateSet childStateSet = + childContext.getAccessibleStateSet(); + if (childStateSet == null) { + throw new RuntimeException( + "getAccessibleStateSet returned null for List child " + + i); + } + + boolean accessibleSelected = + childStateSet.contains(AccessibleState.SELECTED); + boolean listSelected = list.isIndexSelected(i); + + if (accessibleSelected != listSelected) { + throw new RuntimeException( + "getAccessibleStateSet reports that list item " + i + + (accessibleSelected ? " is " : " is not ") + + "selected but List reports that it " + + (listSelected ? "is" : "is not") + " selected"); + } + } + } + + private static void verifyContainerChildren(Component component, + String componentName) { + AccessibleContext context = component.getAccessibleContext(); + + int childCount = context.getAccessibleChildrenCount(); + if (childCount != component.getAccessibleContext() + .getAccessibleChildrenCount()) { + throw new RuntimeException( + "getAccessibleChildrenCount returned an incorrect value " + + "for " + componentName); + } + + for (int i = 0; i < childCount; i++) { + Accessible child = context.getAccessibleChild(i); + if (child == null) { + throw new RuntimeException( + "getAccessibleChild returned null for " + + componentName + " child " + i); + } + + AccessibleContext childContext = child.getAccessibleContext(); + if (childContext == null) { + throw new RuntimeException( + "getAccessibleContext returned null for " + + componentName + " child " + i); + } + } + } + + private static void assertExpectedString(String methodName, + String expected, + String actual) { if (expected == null) { - throw new RuntimeException("Excepted value is null. Provide " + - "excepted value"); + throw new RuntimeException( + "Expected value for " + methodName + " should not be null"); } if (actual == null) { - throw new RuntimeException(methodName + " returned null; expected" + - " [" + expected + "]"); + throw new RuntimeException( + methodName + " returned null; expected [" + expected + "]"); } + if (!expected.equals(actual)) { - throw new RuntimeException(methodName + " returned [" + actual + - "]; expected [" + expected + "]"); + throw new RuntimeException( + methodName + " returned [" + actual + + "]; expected [" + expected + "]"); } } - private static void assertPresence(String methodName, boolean expectedPresent, Object value) { + private static void assertPresence(String methodName, + boolean expectedPresent, + Object value) { if (expectedPresent && value == null) { - throw new RuntimeException(methodName + " returned null but was expected"); + throw new RuntimeException( + methodName + " returned null but should not"); } + if (!expectedPresent && value != null) { - throw new RuntimeException(methodName + " returned non-null but " + - "was expected to be null"); + throw new RuntimeException( + methodName + " returned non-null but should return null"); } } - private static void assertLocaleMatches(Component component, AccessibleContext context) { + private static void assertLocaleMatches(Component component, + AccessibleContext context) { Locale componentLocale = component.getLocale(); Locale accessibleLocale = context.getLocale(); if (componentLocale == null) { throw new RuntimeException("Component.getLocale returned null"); } + if (accessibleLocale == null) { - throw new RuntimeException("AccessibleContext.getLocale returned null"); + throw new RuntimeException( + "AccessibleContext.getLocale returned null"); } + if (!componentLocale.equals(accessibleLocale)) { - throw new RuntimeException(String.format( - "AccessibleContext.getLocale returned [%s], but Component" + - ".getLocale returned [%s]", - accessibleLocale, componentLocale - )); + throw new RuntimeException( + "AccessibleContext.getLocale returned [" + + accessibleLocale + "], but Component.getLocale returned [" + + componentLocale + "]"); } } - private static void assertIntValueEquals(String methodName, int expected, Number actual) { + private static void assertIntValueEquals(String methodName, + int expected, + Number actual) { if (actual == null) { - throw new RuntimeException(methodName + " returned null; expected [" + expected + "]"); + throw new RuntimeException( + methodName + " returned null; expected [" + expected + "]"); } + if (actual.intValue() != expected) { throw new RuntimeException( - methodName + " returned [" + actual + "]; expected [" + expected + "]" - ); + methodName + " returned [" + actual + + "]; expected [" + expected + "]"); } } } diff --git a/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java b/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java index 229ab03b568..9e2c5e909b0 100644 --- a/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java +++ b/test/jdk/sun/security/ssl/CipherSuite/DisabledCipherSuitesNotNegotiated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -32,13 +32,15 @@ import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import jdk.test.lib.security.SecurityUtils; -import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.security.SecurityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; @@ -50,29 +52,32 @@ import javax.net.ssl.SSLHandshakeException; public class DisabledCipherSuitesNotNegotiated { private static final String TLS_PROTOCOL = "TLSv1.2"; private static volatile int serverPort = 0; - private static volatile Exception serverException = null; private static final CountDownLatch waitForServer = new CountDownLatch(1); - private static final int WAIT_FOR_SERVER_SECS = 5; + private static final int WAIT_FOR_SERVER_SECS = (int)Utils.adjustTimeout(5); private static final String DISABLED_CIPHERSUITE = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; private static final String DISABLED_CIPHER_WILDCARD = "TLS_ECDH*WITH_AES_256_GCM_*"; + private static volatile Exception serverException = null; private static void runServer(boolean disabledInClient) throws Exception { SSLContext ctx = SSLContext.getInstance(TLS_PROTOCOL); ctx.init(null, null, null); SSLServerSocketFactory factory = ctx.getServerSocketFactory(); + InetAddress address = InetAddress.getLoopbackAddress(); + System.out.println("SERVER listening on " + address); try(SSLServerSocket serverSocket = (SSLServerSocket)factory - .createServerSocket(0, -1, InetAddress.getLoopbackAddress())) { - serverPort = serverSocket.getLocalPort(); - waitForServer.countDown(); - + .createServerSocket(0, -1, address)) { if (disabledInClient) { // set cipher suite to disabled ciphersuite serverSocket.setEnabledCipherSuites(new String[]{DISABLED_CIPHERSUITE}); } - try(SSLSocket clientSocket = (SSLSocket) serverSocket.accept()) { + serverPort = serverSocket.getLocalPort(); + serverSocket.setSoTimeout(WAIT_FOR_SERVER_SECS * 3000); + waitForServer.countDown(); + + try(SSLSocket clientSocket = (SSLSocket)serverSocket.accept()) { try { clientSocket.getInputStream().readAllBytes(); throw new Exception("SERVER: The expected handshake exception was not thrown."); @@ -88,7 +93,9 @@ public class DisabledCipherSuitesNotNegotiated { SSLContext ctx = SSLContext.getInstance(TLS_PROTOCOL); ctx.init(null, null, null); SSLSocketFactory factory = ctx.getSocketFactory(); - try(SSLSocket socket = (SSLSocket)factory.createSocket("localhost", portNumber)) { + InetAddress address = InetAddress.getLoopbackAddress(); + System.out.println("CLIENT: Connecting to " + address); + try(SSLSocket socket = (SSLSocket)factory.createSocket(address, portNumber)) { if (!disableInClient) { socket.setEnabledCipherSuites(new String[]{DISABLED_CIPHERSUITE}); } @@ -104,42 +111,7 @@ public class DisabledCipherSuitesNotNegotiated { public static void main(String [] args) throws Exception { if (args.length == 1) { - // run server-side - final boolean disabledInClient = args[0].equals("client"); - if (!disabledInClient) { - SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); - } - try(ExecutorService executorService = Executors.newSingleThreadExecutor()) { - executorService.submit(() -> { - try { - runServer(disabledInClient); - } catch (Exception exc) { - System.out.println("Server Exception:"); - exc.printStackTrace(System.out); - serverException = exc; - throw new RuntimeException(exc); - } - }); - - if (!waitForServer.await(WAIT_FOR_SERVER_SECS, TimeUnit.SECONDS)) { - throw new Exception("Server did not start within " + - WAIT_FOR_SERVER_SECS + " seconds."); - } - - System.out.printf("Server listening on port %d.%nStarting client process...", - serverPort); - - OutputAnalyzer oa = ProcessTools.executeProcess( - ProcessTools.createTestJavaProcessBuilder("DisabledCipherSuitesNotNegotiated", - "" + disabledInClient, "" + serverPort)); - oa.shouldHaveExitValue(0); - System.out.println("Client output:"); - System.out.println(oa.getOutput()); - if (serverException != null) { - throw new Exception ("Server-side threw an unexpected exception: " - + serverException); - } - } + runTest(args[0].equals("client")); } else if (args.length == 2) { // run client-side @@ -147,6 +119,7 @@ public class DisabledCipherSuitesNotNegotiated { if (disabledInClient) { SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); } + runClient(Boolean.parseBoolean(args[0]), Integer.parseInt(args[1])); } else { @@ -155,4 +128,48 @@ public class DisabledCipherSuitesNotNegotiated { } } + private static void runTest(final boolean disabledInClient) throws Exception { + try(ExecutorService executorService = Executors.newSingleThreadExecutor()) { + Future serverThread = executorService.submit(() -> { + try { + if (!disabledInClient) { + SecurityUtils.addToDisabledTlsAlgs(DISABLED_CIPHER_WILDCARD); + } + runServer(disabledInClient); + } catch (Exception exc) { + serverException = exc; + } + }); + + + if (!waitForServer.await(WAIT_FOR_SERVER_SECS, TimeUnit.SECONDS)) { + throw new Exception("Server did not start within " + + WAIT_FOR_SERVER_SECS + " seconds."); + } + + System.out.printf("Server listening on port %d.%nStarting client process...", + serverPort); + + OutputAnalyzer oa = ProcessTools.executeProcess( + ProcessTools.createTestJavaProcessBuilder( + "DisabledCipherSuitesNotNegotiated", + "" + disabledInClient, "" + serverPort)); + oa.waitFor(); + serverThread.get(); + + System.out.printf("Client process return %d%nCLIENT OUTPUT%n%s%n", + oa.getExitValue(), oa.getOutput()); + if (serverException != null) { + System.out.printf( + "Server thread threw an unexpected exception: %s%n", + serverException); + throw serverException; + } else if (oa.getExitValue() != 0) { + throw new Exception(String.format("Client exit code is non-zero (%d). "+ + "Server did not throw an exception.", + oa.getExitValue())); + } + } + } + } diff --git a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java index ffa8a530859..16a48fcc626 100644 --- a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java +++ b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java @@ -103,9 +103,9 @@ public class TestErasure extends JavadocTester { checkOutput("Foo.html", true, """
  • Constructor Details
      -
    1. Foo(T)
    2. -
    3. Foo(T)
    4. -
    5. Foo(T)
    6. +
    7. Foo(T)
    8. +
    9. Foo(T)
    10. +
    11. Foo(T)
  • """); checkOutput("index-all.html", true, """ @@ -145,9 +145,9 @@ public class TestErasure extends JavadocTester { checkOutput("Foo.html", true, """
  • Method Details
      -
    1. m(T)
    2. -
    3. m(T)
    4. -
    5. m(T)
    6. +
    7. m(T)
    8. +
    9. m(T)
    10. +
    11. m(T)
  • """); checkOutput("index-all.html", true, """ @@ -210,8 +210,8 @@ public class TestErasure extends JavadocTester { checkOutput("Foo.html", true, """
  • Constructor Details
      -
    1. Foo(T)
    2. -
    3. Foo(T)
    4. +
    5. Foo(T)
    6. +
    7. Foo(T)
  • """); checkOutput("index-all.html", true, """ @@ -242,8 +242,8 @@ public class TestErasure extends JavadocTester { checkOutput("Foo.html", true, """
  • Method Details
      -
    1. m(T)
    2. -
    3. m(T)
    4. +
    5. m(T)
    6. +
    7. m(T)
  • """); checkOutput("index-all.html", true, """ diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 17ab9734845..02100d84a1a 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -25,7 +25,7 @@ * @test * @bug 7025314 8023700 7198273 8025633 8026567 8081854 8196027 8182765 * 8196200 8196202 8223378 8258659 8261976 8320458 8329537 8350638 - * 8342705 8371021 8373526 + * 8342705 8371021 8373526 8384065 * @summary Make sure the Next/Prev Class links iterate through all types. * Make sure the navagation is 2 columns, not 3. * @library /tools/lib ../../lib @@ -172,6 +172,36 @@ public class TestNavigation extends JavadocTester { tb.writeJavaFiles(src, """ package pkg1; public class A { + /** + * Empty ctor + */ + public A() {} + + /** + * Single param ctor + */ + public A(int i) {} + + /** + * A ctor with many params + */ + public A(int i, int j, int x, int y, String s, boolean b) {} + + /** + * A method without parameters + */ + public void noParams() {} + + /** + * A method with a single parameter + */ + public void oneParam(String s) {} + + /** + * A method with lots of parameters + */ + public void manyParams(String s, int i, int j, boolean b, double d, double e) {} + /** * Class with members. */ @@ -217,6 +247,29 @@ public class TestNavigation extends JavadocTester { "pkg1"); checkExit(Exit.OK); + checkOrder("pkg1/A.html", + """ +
      +
    1. Description
    2. +
    3. Nested Class Summary
    4. +
    5. Constructor Summary
    6. +
    7. Method Summary
    8. +
    9. Constructor Details +
        +
      1. A()
      2. +
      3. A(int)
      4. +
      5. A(int, int, int, int, String, boolean)
      6. +
      +
    10. +
    11. Method Details +
        +
      1. noParams()
      2. +
      3. oneParam(String)
      4. +
      5. manyParams(String, int, int, boolean, double, double)
      6. +
      +
    12. +
    """); + checkOrder("pkg1/A.X.html", """